Python3 共享扩展不链接库依赖项

Bog*_* M. 6 python distutils setup.py

我正在为我的库创建一个共享的 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])
Run Code Online (Sandbox Code Playgroud)

运行$ setup.py build结果会成功构建共享扩展模块,但它没有与"bbmputil"库链接。

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

libbbmputil.solibraries尽管在kwarg中指定,但无处可寻Extension()

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


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

linux-vdso.so.1 (0x00007ffc85ce1000)
libc.so.6 => /usr/lib/libc.so.6 (0x00007f49f0d70000)
/usr/lib64/ld-linux-x86-64.so.2 (0x00007f49f0f74000)
Run Code Online (Sandbox Code Playgroud)
>>> 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
Run Code Online (Sandbox Code Playgroud)

其中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
Run Code Online (Sandbox Code Playgroud)
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
Run Code Online (Sandbox Code Playgroud)

在第二次调用中,在构建共享扩展时,两者-lbbmputil-R被正确传递,所以我没有想法。


产生相同行为的最小示例

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

$ env PYTHONPATH="sharedextension_build_path" python3
Run Code Online (Sandbox Code Playgroud)
>>> 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
Run Code Online (Sandbox Code Playgroud)
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
Run Code Online (Sandbox Code Playgroud)
linux-vdso.so.1 (0x00007ffd0b9e5000)
libc.so.6 => /usr/lib/libc.so.6 (0x00007fab528e8000)
/usr/lib64/ld-linux-x86-64.so.2 (0x00007fab52aec000)
Run Code Online (Sandbox Code Playgroud)

再次强调,libm.so依赖性无处可寻。


环境:

  • python3 3.8.1
  • linux 5.4.6
  • 海湾合作委员会9.2.0
  • LD 2.33.1
  • LDD 2.3.0

ral*_*htp 3

更新:这种情况下的问题是默认启用的链接器优化选项 ,请参阅 使用 gcc -l 后在 ldd 中缺少库--as-needed

添加--no-as-needed修复了此错误

为了调试链接器错误,您可以使用在运行时抛出链接器错误的可执行文件在LD_DEBUG=files,libs /usr/local/ABC/bin/ABC哪里,参见http://www.bnikolic.co.uk/blog/linux-ld-debug.htmllibm.so.6:无法打开共享目标文件:没有这样的文件或目录在linux上,您可以使用ie找到一个(我想您知道这一点)ABC.solocate libm

由于链接是动态的,因此可以选择使用该选项或等效的gcc 链接器选项来指定.so可以找到文件 的路径,并且出于调试和测试的原因,我将使用绝对路径https://docs .python.org/2/distutils/apiref.htmllibrary_dirsdisutils.core-LLD_LIBRARY_PATH

在你的 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])
Run Code Online (Sandbox Code Playgroud)

您使用链接器标志在 gcc 调用中-R指定,参见 distutils 的共享库依赖项gcc -R 参数的作用是什么?https://www.mpcdf.mpg.de/services/computing/software/libraries/static-and-dynamic-linking-on-linux-systems中描述了链接过程。据说,或者等效地,gcc 链接器选项会覆盖 rpath,并且应该避免它,但是无论如何你都应该尝试一下......rpathLD_LIBRARY_PATH-L

此行为的另一种可能性可能是权限问题,即当您执行时example它是否有权访问libmcf https://unix.stackexchange.com/questions/303292/permission-denied-on-some-shared-libraries