在构建python / cython扩展时指定替代链接器?

时间:2020-03-03 17:25:15

标签: python c++ linker cython

为加快开发速度,我一直在尝试在编译一些cython扩展时尝试使用“黄金”链接器或多线程“ lld”链接器代替GNU链接器。在我的setup.py中,我尝试了以下操作:

lld_linker = shutil.which('ld.lld')
if lld_linker:
    print("Using LLD Linker in place of GNU LD")
    os.environ['LDSHARED'] = lld_linker    

但是,这会导致链接过程失败,并出现大量“ / usr / bin / ld:.....对.....的未定义引用”错误。 (无需添加此LDSHARED envvar即可正常运行)。无论使用此内部os.environ还是在调用setup.py之前导出envvar,故障行为都是相同的。我有一种预感,也许Cython的用于分配编译作业的多处理方法不会在所有地方都保持环境变量,从而导致链接器的这种混合?

如何正确指定链接器,以便设置和构建与GNU ld链接器相同?

这里有一个相关的问题: How do I specify the linker when building python extensions?;但是,如前所述,它并不能解决我的问题。

1 个答案:

答案 0 :(得分:1)

通常,distutils / setuptools不直接使用链接器,而是调用gcc之类的前端作为c扩展,或调用g++之类作为c ++扩展。

这些前端收集所有必要的信息-例如应将哪些库传递给链接器,例如libstdc++(用于c ++扩展名),然后使用正确的命令行选项调用链接器。例如,通过-v中的gccg++-选项传递给extra_link_args前端的setup.py-时,人们可以看到它。

因此,如果您强制distutuls / setuptools.py直接使用ld,则还应该在extra_link_args中提供前端收集的所有选项,否则某些库将丢失如您所见,并且编译将失败。

setup.py选择另一个链接器是很困难的,但是有一些便宜的选择可以在本地进行:

  1. 默认链接器(例如/usr/bin/ld)只是一个符号链接,请使其指向您选择的链接器。
  2. 通过extra_link_args,即-B/path/to/folder/with/my/linker传递-B-option。这些细微的细节是:1)应该将链接器称为ld(如果需要,创建一个符号链接)2)一些发行版(例如Anaconda)已经提供了-B-选项,该选项优先于通过的路径通过extra_link_args。在这种情况下,一种可能的解决方案是像本SO-post中所述,修改发出的命令行。
  3. 直接通过LDSHARED环境变量设置链接器,并在extra_link_args中提供所有需要的选项。

选项2可能最容易调整以在任何系统上工作:

  1. 检测是否存在ld.lld,如果存在:
  2. 创建一个带有符号链接的临时文件夹(称为ld
  3. 将此临时文件夹作为-B选项添加到extra_link_args
  4. 检测发行版是否已经使用-B选项,操作命令行(例如,here所述)以确保临时文件夹的优先级。