Cython构建导致未定义的符号

时间:2014-04-30 14:41:22

标签: python linker installation cython undefined-symbol

我有一个c ++程序,我正在尝试包装/转换为Cython。它使用特定的库,由于某种原因,不会导致导入的工作模块。顺便说一句,有一个工作的c ++程序。这是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,
)

我应该提到它似乎是导致问题的libnmf。 libnmf的第一个版本会导致此脚本生成此错误:

/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

当我使用-fPIC重建libnmf时,setup会生成一个libnmfpy.so,但是当我在另一个脚本中导入它时,我会得到上面提到的未定义符号:

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

如果它会有所帮助,这是我的搜索建议:

nm libnmfpy.so | grep _ZN4elem6lapack3SVDEiiPdiS1_
             U _ZN4elem6lapack3SVDEiiPdiS1_

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

我猜错误的原因是什么。我看一下我认为是libnmf所构建的有问题的库:

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

我对图书馆和链接器不太熟悉,所以任何帮助都会受到赞赏。感谢

编辑:一点点挖掘让我意识到了什么。我应该注意Mac OS X和Linux之间的区别吗?我为之工作的人写的最初报告没有像这样的构建错误

2 个答案:

答案 0 :(得分:3)

您应该使用nm -C来解开符号。它看起来像是混合静态和共享库,这通常不是一个好主意。此外,gcc的链接器是一个通道链接器,这意味着库标志的顺序很重要。您希望以反向依赖顺序列出库。换句话说,如果a依赖于b,则b必须出现在链接器标志中的a之前。

答案 1 :(得分:1)

我无法尝试重新创建您的设置,然后在我的设置上测试解决方案,因为我没有您的来源,但在我看来,当您使用fpic重新编译libnmf时,它是在动态链接之前重新编译的,而之前它是静态链接的。

如果我的猜测是正确的,那么您可以尝试:

  1. 使用-fPIC-static再次编译libnmf。
  2. 更改您的setup.py - 将"elemental"添加到libraries列表 - 这将使链接器也获取该lib。
  3. 你应该注意到方法#1通常被认为不太理想,但正如我所说,它可能是最初以这种方式编译的。但是,#2可能需要更多的工作,因为如果还有其他需要的库,你也必须找到并添加它们。