Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Cython build resulting in undefined symbol

I've got a c++ program I'm trying to wrap/convert to Cython. It uses a particular library that for some reason, will not result in a working module for importing. There is a working c++ program, by the way. Here's the setup.py:

ext_modules = [
Extension(
    name="libnmfpy",
    sources=["interface/nmf_lib.pyx"],
    include_dirs = ["../src/", numpy.get_include()],
    libraries=["nmf","mpi_cxx","mpi","m"],
    library_dirs=["../build/Linux/bin.release","/usr/local/lib/","/usr/lib"],
    language="c++",)
]

setup(
name = 'libnmfpy',
cmdclass = {'build_ext': build_ext},
ext_modules = ext_modules,
)

I should mention it is libnmf that seems to be causing problems. The first build of libnmf would cause this script to generate this error:

/usr/bin/ld: ../build/Linux/bin.release/libnmf.a(nmf.o): relocation R_X86_64_32 against `.rodata' can not be used when making a shared object; recompile with -fPIC
../build/Linux/bin.release/libnmf.a: could not read symbols: Bad value
collect2: error: ld returned 1 exit status

When I rebuild libnmf with -fPIC, setup generates a libnmfpy.so, but when I import that in another script, I would get the aforementioned undefined symbol:

Traceback (most recent call last):
File "test.py", line 1, in <module>
    import libnmfpy
ImportError: $path/cython/libnmfpy.so: undefined symbol: _ZN4elem6lapack3SVDEiiPdiS1_

If it would help, here's something my search suggested:

nm libnmfpy.so | grep _ZN4elem6lapack3SVDEiiPdiS1_
             U _ZN4elem6lapack3SVDEiiPdiS1_

nm ../build/Linux/bin.release/libnmf.a | grep _ZN4elem6lapack3SVDEiiPdiS1_
             U _ZN4elem6lapack3SVDEiiPdiS1_

Which is what I guess to the cause of the error. I look in what I think is the offending library that libnmf is built on:

nm $another_path/lib/libelemental.a | grep _ZN4elem6lapack3SVDEiiPdiS1_
0000000000005290 T _ZN4elem6lapack3SVDEiiPdiS1_

I am not too familiar yet with libraries and linkers, so any help would be appreciated. Thanks

edit: a little digging made me realize something. Is there a difference between Mac OS X and Linux that I should watch out for? The people I work for that wrote this originally reported no build errors like this

like image 236
Ben Avatar asked Apr 30 '14 14:04

Ben


2 Answers

You should use nm -C, to unmangle your symbols. It also looks like you are mixing static and shared libraries which is generally not a good idea. Also, gcc's linker is a one pass linker which means the order of library flags matters. You want to list the libraries in reverse dependency order. In other words, if a depends on b, then b must appear before a in the linker flags.

like image 170
b4hand Avatar answered Oct 31 '22 03:10

b4hand


Well I can't try to recreate your setup and then work out and test a solution on my setup since I don't have your source, but it seems to me that when you recompiled libnmf with fpic, it was recompiled with dynamic linking, while before it used to be statically linked.

If my guess is correct, then you can try either:

  1. compiling libnmf again with -fPIC , AND -static.
  2. changing your setup.py - add "elemental" to the libraries list - this will make the linker fetch that lib as well.

You should note that approach #1 is usually considered less desirable, but as I said it could be that it was originally compiled that way anyways. #2, however, could take more work because if there are other libs that are required, you will have to find and add them as well.

like image 1
itai Avatar answered Oct 31 '22 04:10

itai