为了加快开发过程,我一直在尝试在编译一些 cython 扩展时尝试使用“gold”链接器或多线程“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: ..... undefined reference to .....”错误。 (构建工作正常,无需添加此 LDSHARED envvar)。无论是使用这个内部 os.environ,还是在调用 setup.py 之前导出 envvar,失败行为都是相同的。我有一种预感,也许 Cython 分发编译作业的多处理方法并没有将环境变量保留在任何地方,从而导致了这种链接器的混合?
如何正确指定链接器,以便设置与 GNU ld 链接器相同且构建相同?
这里有一个相关的问题:
How do I specify the linker when building python extensions? ;但是,如前所述,它并没有解决我的问题。
最佳答案
通常 distutils
/setuptools
不要直接使用链接器,而是调用像 gcc
这样的前端对于 c 扩展或 g++
用于 c++ 扩展。
这些前端收集所有必要的信息——比如应该将哪些库传递给链接器,例如libstdc++
对于 c++ 扩展, - 并使用正确的命令行选项调用链接器。路过-v
时可以看到-gcc
的选项- g++
-前端例如通过extra_link_args
在 setup.py
.
所以如果你强制 distutuls
/setuptools.py
使用 ld
您还应该直接在 extra_link_args
中提供前端收集的所有选项,否则一些库将丢失并且编译将失败,如您所见。
让setup.py
选择另一个链接器,但有一些便宜的选择可以在本地进行:
/usr/bin/ld
)只是一个符号链接(symbolic link),让它指向您选择的链接器。 -B
-option通过 extra_link_args
,即 -B/path/to/folder/with/my/linker
.微妙的细节是:1)链接器应该被称为ld
。 (如果需要,创建一个符号链接(symbolic link)) 2)一些发行版(例如 Anaconda)已经提供了 -B
-option,优先于通过extra_link_args
传递的路径.在这种情况下,一种可能的解决方案是修改发出的命令行,类似于 SO-post 中所述。 . LDSHARED
设置链接器环境变量并在 extra_link_args
中提供所有需要的选项. 选项 2 可能最容易调整以适用于任何系统:
ld.lld
是出席,如果是:ld
)-B
-extra_link_args
的选项-B
选项,操作命令行(如 here 所述)以确保临时文件夹的优先级。 关于python - 在构建 python/cython 扩展时指定替代链接器?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60512552/