Python 具有distutils的共享库依赖项

Python 具有distutils的共享库依赖项,python,distribution,packaging,distutils,software-distribution,Python,Distribution,Packaging,Distutils,Software Distribution,我是distutils的新手,我有一个问题让我陷入困境。我正在编译一个需要扩展的包,因此我将扩展如下: a_module = Extension( "amodule", ["initmodule.cpp"], library_dirs=libdirs, extra_objects = [ "unix/x86_64/lib/liba.so"

我是distutils的新手,我有一个问题让我陷入困境。我正在编译一个需要扩展的包,因此我将扩展如下:

    a_module = Extension(
          "amodule",
          ["initmodule.cpp"],
          library_dirs=libdirs,
          extra_objects = [
                    "unix/x86_64/lib/liba.so"
                    "unix/x86_64/lib/lib.so",
                    "unix/x86_64/lib/libc.so"],
    )
然后运行安装方法:

    setup(name="apackage", version="7.2",
      package_dir = {'':instdir+'/a/b/python'},
      packages=['apackage','package.tests'],
      ext_modules=[hoc_module]
)
软件包分发是正确的,我可以“python setup.py install”很好,但是当我尝试导入我的软件包时,我得到了一个错误
ImportError:liba.so.0:无法打开共享对象文件:没有这样的文件或目录

我意识到,当我将liba.so.0的位置添加到我的LD_LIBRARY_路径时,程序运行良好。不幸的是,我没有编写这些模块,对编译也没有很好的理解。我已经想了好几天了,但都没有结果

更新:我尝试将liba.a、libb.a等文件传递给额外的\u对象,但无效,生成以下错误:liba.a:无法读取符号:错误值 collect2:ld返回了1个退出状态。我想做的是打包一个python模块,它需要编译一个库,而这个库本身依赖于我需要在包中包含的其他库。我怀疑我的问题与这个非常相似:但那个问题没有解决,我想可能是因为它已经存在了两年,所以找到了一个解决方案

更新2:目前,我通过以下方式解决了此问题:

      data_files=[('/usr/local/lib', glob.glob('unix/x86_64/lib/*'))]

也就是说,我正在将我需要的库复制到/usr/local/lib中。然而,我对这个解决方案不太满意,这不仅是因为它要求我的用户拥有root权限,还因为这可能仍然无法在Redhat发行版上运行。因此,如果有人能提出比此修复更好的建议,请告诉我。

扩展名类的
额外对象
参数与其说是链接到扩展名的库列表,不如说是将传递给链接器的对象文件列表(而且文件名不应该包括扩展名,因为distutils会添加这些扩展名。)它并不能满足您的需要

如果您想链接特定的共享库,正如这些文件的名称所表明的那样,您必须做两件事:告诉distutils让编译器链接这些共享库,并告诉动态链接器(通常是
ld.so
)在哪里可以找到这些共享库。您可以告诉distutils,让编译器通过使用
扩展名
参数来链接库,该参数应该是库名称列表(没有
lib
前缀和
后缀)。在您的示例中,它似乎是
['a',b',c']
(虽然看起来像是
'b'
'lib.掉下来,所以
'和
'c'
实际上会与系统libc发生冲突。)

通过设置
LD\u LIBRARY\u PATH
环境变量,或通过更改系统范围的配置设置(使用
ldconfig
或编辑
/etc/LD.so.conf
),可以告诉链接器在何处查找这些共享库,或者通过在扩展模块中对搜索路径进行硬编码;您可以通过将
运行时库\u dirs
参数传递到
扩展
来实现后者。但是,硬编码路径确实有其自身的问题——您必须将这些库保持在同一位置,并且扩展模块的所有用户都可以访问这些库


(或者,您可以使用静态链接而不是动态链接,例如,只提供静态形式的库,
liba.a
存档(在这种情况下,distutils将自动静态链接到它们)。这基本上意味着整个库都包含在扩展模块中,扩展模块具有各种优缺点。)

您可以在输出二进制文件中搜索链接器存储路径,这样就不需要LD_LIBRARY_路径。一些示例:

# Will link fine but at run-time LD_LIBRARY_PATH would be required
gcc -o blah blah.o -lpcap -L/opt/csw/lib

# Without LD_LIBRARY_PATH=/opt/csw/lib it will fail to link, but
# it wouldn't be needed at run-time
gcc -o blah blah.o -lpcap -Wl,-R/opt/csw/lib

# LD_LIBRARY_PATH not needed at link or run-time
gcc -o blah blah.o -lpcap -Wl,-{L,R}/opt/csw/lib

# This makes it possible to use relative paths; run `readelf -d binary_name`
# and you'll see '$ORIGIN/../lib/' in RPATH.  This plus `-zorigin` make it look
# relative to the binary for libraries at run-time
gcc -o blah blah.o -lsomelib -L/whatever/path/floats/your/boat -Wl,-R'$ORIGIN/../lib/' -Wl,-zorigin
…其中:

  • 链接时使用带有
    -L
    的路径
  • -R
    给出的路径在运行时使用

非常感谢您详细而出色的回答。我对runtime_library_dirs应设置为相对路径的理解正确吗,否则我看不出它是如何硬编码的?此外,我是否应该传递静态链接库(即liba.a归档文件)到库或额外的\u对象关键字。不幸的是,文档在这两个问题上对我帮助不大。可以将相对目录作为运行时\u库\u目录传递,但这不是一个好主意(因为扩展模块在构建过程中会移动,并且所有人都必须使用相同的路径)至于静态链接,您可以尝试将
.a
存档作为
extra\u objects
参数传递,尽管这不是
extra\u objects
的目的,我不确定它是否有效。也许您应该详细说明您实际想要做什么。感谢您的回答,我已经为我的原始问题添加了更多细节.好的-我发现解决我的问题的一种方法是将库放在/usr/lib中。我意识到这并不理想,但有什么主要原因我不应该这样做吗?没有,将共享库放在动态链接器已经考虑过的位置是常见的做法。不这样做的唯一原因是如果有其他东西,比如操作系统包Manager、控件<代码> /UR/LIB < /代码>,在这种情况下,当您稍后安装其他OS包时,您的文件可能会出现问题。<代码> /Ur/Studio/LIB < /代码>是一个更好的选择(并且存在于此目的)。您还可以使用其他位置并告诉动态链接器来考虑它。(通过
/etc/ld.so.conf
ldconfig-m
命令或类似命令。)非常好的答案,通过将您的答案与此相结合,我能够以所需的方式构建所需的模块。非常感谢。没问题,我很高兴我能为您提供帮助。I:您可以添加
-R'$ORIGIN/./lib/'
选项,而不是添加
运行时库\u dirs=“$OR