我正在为我的库创建一个共享的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
尽管在libraries
的Extension()
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
。
环境:
.so
的library_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 distutils和What 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的权限