Python3共享扩展不';针对库依赖的t链接

Python3共享扩展不';针对库依赖的t链接,python,setup.py,distutils,Python,Setup.py,Distutils,我正在为我的库创建一个共享Python扩展,并使用distutils来构建它 以下是mysetup.py的相关部分: 将distuitls.core导入为dc 从os.path导入联接为路径\联接 模块=dc.扩展(模块名称, sources=[path_join(介子src_根,“py3_绑定”,“module.c”)], include_dirs=[path_join(介子src_根,“include”), 库=[“bbmputil”], 运行时\库\目录=[介子\构建\根]) dc.设置(

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

以下是my
setup.py
的相关部分:

将distuitls.core导入为dc
从os.path导入联接为路径\联接
模块=dc.扩展(模块名称,
sources=[path_join(介子src_根,“py3_绑定”,“module.c”)],
include_dirs=[path_join(介子src_根,“include”),
库=[“bbmputil”],
运行时\库\目录=[介子\构建\根])
dc.设置(名称=模块名称,
版本=模块版本,
description=“bbmp_utils库的Python3绑定”,
ext_模块=[模块])

运行
$setup.py build
会成功生成共享扩展模块,但它不会链接到
“bbmputil”

$ldd build/lib.linux-x86_64-3.8/bbmp_utils.cpython-38-x86_64-linux-gnu.so
libbbmputil.so
尽管在
Extension()
库中指定,但仍然找不到

它确实存在于
runtime\u library\u dirs
kwarg中指定的位置


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

$env PYTHONPATH=“sharedextension\u build\u path”python3
其中,
bbmp\u 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
在第二次调用中,在构建共享扩展时,
-lbbmputil
-R
都被正确地传递,所以我没有主意了


产生相同行为的最小示例 试图构建利用数学共享库中的函数和其他符号的模块:

#/usr/bin/env蟒蛇3
将distutils.core导入为dc
module=dc.Extension('示例',
sources=['example.c'],
库=['m'])
dc.setup(名称='example',
版本='0.1',
ext_模块=[模块])
$./setup.py构建
$ldd…/…/example.cpython-38-x86_64-linux-gnu.so

同样地,
libm。因此,
依赖关系找不到


环境:

  • 蟒蛇3.8.1
  • linux 5.4.6
  • gcc 9.2.0
  • ld 2.33.1
  • LDD2.3.0
更新:本例中的问题是链接器优化选项
--根据需要
默认启用的,请参阅

根据需要添加
--no
可修复此错误

对于调试链接器错误,您可以使用
LD_DEBUG=files,libs/usr/local/ABC/bin/ABC
,其中
ABC
是在运行时抛出链接器错误的可执行文件,cf在linux上,您可以找到
。因此
使用
查找libm
(我想您知道这一点)

由于链接是动态的,因此可以选择指定
的路径。因此可以使用
distils.core的
library\u dirs
选项找到
文件,即
-L
或等效的
LD\u library\u路径
gcc链接器选项,出于调试和测试的原因,我将使用绝对路径()

在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和。中是链接过程的描述。据说,
LD_LIBRARY_PATH
或等效的
-L
gcc链接器选项会覆盖rpath,应该避免使用它,但是无论如何,您应该尝试一下


此行为的另一个可能原因是权限问题,即当您执行
示例
时,它是否有权限访问
libm
cf

生成日志是否显示了。因此,与bbmputil链接?它显示了我在问题中列出的两个编译器调用。后者(将.o链接到.so)将
-lbbmp
传递到gcc,并将
-R..
正确地传递到链接器。我认为您不理解这个问题。问题不是动态链接器在运行时找不到共享库,而是
ldd
甚至没有将其列为依赖项。因此链接器甚至没有理由在运行时查找它。如果
ldd
没有列出库,这仍然可能是库路径问题,cf在进行更多搜索时,还有其他可能出现此错误的情况,如默认优化标志。截至目前,我还尝试使用
LD_LIBRARY_PATH
以及将绝对路径传递给
LIBRARY_dirs
kwarg,但均未成功。仅使用
LD\u PRELOAD
env预加载库。var似乎起作用了。我将深入探讨答案@ralf htp linked。
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
linux-vdso.so.1 (0x00007ffd0b9e5000)
libc.so.6 => /usr/lib/libc.so.6 (0x00007fab528e8000)
/usr/lib64/ld-linux-x86-64.so.2 (0x00007fab52aec000)
#!/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])