Python3 共享扩展不 link 反对库依赖
Python3 shared extension doesn't link against library dependency
我正在为我的图书馆创建一个共享 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
无处可寻,尽管在 Extension()
的 libraries
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
- 海湾合作委员会 9.2.0
- ld 2.33.1
- ldd 2.3.0
UPDATE : The problem in this case is the linker optimization option
--as-needed
that is enabled by default, see
Missing a library in ldd after using gcc -l
Adding --no-as-needed
fixes this error
要调试链接器错误,您可以使用 LD_DEBUG=files,libs /usr/local/ABC/bin/ABC
,其中 ABC
是在运行时抛出链接器错误的可执行文件,请参见 http://www.bnikolic.co.uk/blog/linux-ld-debug.html and libm.so.6: cannot open shared object file: No such file or directory 在 linux 上,您找到一个 .so
即 locate libm
(我想你知道这一点)
由于链接是动态的,因此可以使用 disutils.core
的 library_dirs
选项指定可以找到 .so
文件的路径,即 -L
或等效的 LD_LIBRARY_PATH
gcc 链接器选项,出于调试和测试的原因,我将使用 绝对路径 (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
,cf Shared library dependencies with distutils and What does the gcc -R parameter do? . In 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
我正在为我的图书馆创建一个共享 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
无处可寻,尽管在 Extension()
的 libraries
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
- 海湾合作委员会 9.2.0
- ld 2.33.1
- ldd 2.3.0
UPDATE : The problem in this case is the linker optimization option
--as-needed
that is enabled by default, see Missing a library in ldd after using gcc -lAdding
--no-as-needed
fixes this error
要调试链接器错误,您可以使用 LD_DEBUG=files,libs /usr/local/ABC/bin/ABC
,其中 ABC
是在运行时抛出链接器错误的可执行文件,请参见 http://www.bnikolic.co.uk/blog/linux-ld-debug.html and libm.so.6: cannot open shared object file: No such file or directory 在 linux 上,您找到一个 .so
即 locate libm
(我想你知道这一点)
由于链接是动态的,因此可以使用 disutils.core
的 library_dirs
选项指定可以找到 .so
文件的路径,即 -L
或等效的 LD_LIBRARY_PATH
gcc 链接器选项,出于调试和测试的原因,我将使用 绝对路径 (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
,cf Shared library dependencies with distutils and What does the gcc -R parameter do? . In 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