Python3共享扩展名未针对库依赖项进行链接

问题描述 投票:2回答:1

我正在为我的库创建一个共享的Python扩展,并且正在使用distutils来构建它。

这些是我的setup.py的相关部分:

import distuitls.core as dc
from os.path import join as path_join

module = dc.Extension(module_name, 
                      sources = [path_join(meson_src_root, "py3_bindings", "module.c")], 
                      include_dirs = [path_join(meson_src_root, "include")],
                      libraries = ["bbmputil"],
                      runtime_library_dirs = [meson_build_root])

dc.setup(name = module_name,
         version = module_version,
         description = "Python3 bindings for the bbmp_utils library",
         ext_modules = [module])

运行$ setup.py build将导致成功构建共享扩展模块,但未与"bbmputil"库链接。

$ ldd build/lib.linux-x86_64-3.8/bbmp_utils.cpython-38-x86_64-linux-gnu.so
linux-vdso.so.1 (0x00007ffc85ce1000)
libc.so.6 => /usr/lib/libc.so.6 (0x00007f49f0d70000)
/usr/lib64/ld-linux-x86-64.so.2 (0x00007f49f0f74000)

libbbmputil.so尽管在librariesExtension() kwarg中指定,但无处找不到。

它确实存在于runtime_library_dirs kwarg中指定的位置。


当扩展名中引用非链接库中的符号时,这会导致python解释器引发ImportError异常:

$ env PYTHONPATH="sharedextension_build_path" python3
>>> import bbmp_utils
ImportError: /home/bogdan/dev/bbmp_utils/build_dbg/build/lib.linux-x86_64-3.8/bbmp_utils.cpython-38-x86_64-linux-gnu.so: undefined symbol: bbmp_vertflip

其中bbmp_vertflip是库中定义的符号,由于某种原因似乎没有链接。


这两个C编译器调用如下:

gcc -pthread -Wno-unused-result -Wsign-compare -DNDEBUG -g -fwrapv -O3 -Wall -march=x86-64 -mtune=generic -O3 -pipe -fno-plt -march=x86-64 -mtune=generic -O3 -pipe -fno-plt -march=x86-64 -mtune=generic -O3 -pipe -fno-plt -fPIC -I/home/bogdan/dev/bbmp_utils/include -I/usr/include/python3.8 -c /home/bogdan/dev/bbmp_utils/py3_bindings/module.c -o build/temp.linux-x86_64-3.8/home/bogdan/dev/bbmp_utils/py3_bindings/module.o
gcc -pthread -shared -Wl,-O1,--sort-common,--as-needed,-z,relro,-z,now -Wl,-O1,--sort-common,--as-needed,-z,relro,-z,now build/temp.linux-x86_64-3.8/home/bogdan/dev/bbmp_utils/py3_bindings/module.o -L/usr/lib -Wl,--enable-new-dtags,-R/home/bogdan/dev/bbmp_utils/build_dbg -lbbmputil -o build/lib.linux-x86_64-3.8/bbmp_utils.cpython-38-x86_64-linux-gnu.so

[在第二次调用中,在构建共享扩展时,-lbbmputil-R都正确传递,所以我没有主意。


产生相同行为的最小示例

[尝试构建一个使用数学共享库中的函数和其他符号的模块:

#!/usr/bin/env python3

import distutils.core as dc

module = dc.Extension('example',
                      sources = ['example.c'],
                      libraries = ['m'])
dc.setup(name = 'example',
         version = '0.1',
         ext_modules = [module])
$ ./setup.py build
$ ldd .../.../example.cpython-38-x86_64-linux-gnu.so
linux-vdso.so.1 (0x00007ffd0b9e5000)
libc.so.6 => /usr/lib/libc.so.6 (0x00007fab528e8000)
/usr/lib64/ld-linux-x86-64.so.2 (0x00007fab52aec000)

再次,找不到libm.so


环境:

  • python3 3.8.1
  • Linux 5.4.6
  • gcc 9.2.0
  • ld 2.33.1
  • ldd 2.3.0
python setup.py distutils
1个回答
0
投票
由于链接是动态的,因此可以使用.solibrary_dirs选项(即disutils.core或等效的-L gcc链接器选项)指定可以找到LD_LIBRARY_PATH文件的路径。调试和测试的原因我将使用

绝对路径(https://docs.python.org/2/distutils/apiref.html

在您的python最小示例中,代码是:

#!/usr/bin/env python3 import distutils.core as dc module = dc.Extension('example', sources = ['example.c'], library_dirs = ['/usr/lib/x86_64-linux-gnu/libm.so'], libraries = ['m']) dc.setup(name = 'example', version = '0.1', ext_modules = [module])

您使用-R链接器标志在gcc调用中指定rpath,参见Shared library dependencies with distutilsWhat does the gcc -R parameter do?https://www.mpcdf.mpg.de/services/computing/software/libraries/static-and-dynamic-linking-on-linux-systems中描述了链接过程。据说LD_LIBRARY_PATH或等效地-L gcc链接器选项会覆盖rpath,应避免使用它,但是无论如何您都应该尝试一下...

此行为的另一种可能是权限问题,即执行example时是否具有访问libm cf https://unix.stackexchange.com/questions/303292/permission-denied-on-some-shared-libraries的权限
© www.soinside.com 2019 - 2024. All rights reserved.