您好, 欢迎来到 !    登录 | 注册 | | 设为首页 | 收藏本站

使用Cython将Python代码编译为静态链接的可执行文件

使用Cython将Python代码编译为静态链接的可执行文件

遇到的问题显然来自链接器(gcc在后台启动了一个链接器,看到它-只需-v以详细模式启动gcc- )。因此,让我们从简短的提醒开始,说明链接过程的工作原理:

链接器保留需要解析的所有符号的名称。一开始它只是符号main链接检查库时会发生什么?

如果它是静态库,则链接器将查看该库中的每个目标文件,并且如果此目标文件定义了一些查找符号,则将包括整个目标文件(这意味着某些符号已解析,但是一些新的未解析符号可以被添加)。链接器可能需要在静态库上传递多次。

如果它是一个共享库,则链接器将其视为由一个巨大的目标文件组成的库(毕竟,我们必须在运行时加载该库,而不必一遍又一遍地传递修剪未使用的符号):如果至少有一个需要的符号,则整个库是“链接的”(实际上链接不是在运行时发生的,这是一种试运行),如果不是-整个库被丢弃,再也没有看过。

例如,如果您链??接:

gcc -L/path -lpython3.x <other libs> foo.o

无论python3.x是共享库还是静态库,您都会遇到问题:链接器看到它时,它只会查找symbol main,但在python- lib中未定义此符号,因此将python-lib丢弃再也没有看过 仅当链接器看到目标文件foo.o,它才意识到需要整个Python符号,但是现在已经来不及了。

一个简单的规则可以处理此问题:将目标文件放在第一位!这意味着:

gcc -L/path  foo.o -lpython3.x <other libs>

现在,链接器在第一次看到它时就从python-lib知道了它的需求。

还有其他方法可以达到类似的结果。

A)只要每次扫描至少添加一个新的符号定义,链接器就可以重申一组存档:

gcc -L/path --Wl,-start-group -lpython3.x <other libs> foo.o -Wl,-end-group

链接程序选项,-Wl,-start-group-Wl,-end- group链接程序在该组归档中重复进行多次,因此链接程序有第二次(或多次)机会包含符号。此选项可导致更长的链接时间。

B)启用该选项--no-as-needed将导致链接共享库(并且仅共享库),无论是否需要在该库中定义符号。

gcc -L/path -Wl,-no-as-needed -lpython3.x -Wl,-as-needed <other libs> foo.o

实际上,认的ld-behavior是--no-as-needed,但是gcc-frontend用option调用ld --as- needed,因此我们可以通过-no-as-needed在python-library之前添加来恢复行为,然后再次将其关闭

现在到您的静态链接问题。我不建议使用所有标准库的静态版本(在glibc之上),您应该做的只是静态地链接python-library。

链接的规则很简单:认情况下,链接器尝试首先打开库的共享版本,而不是打开静态版本。即,对于图书馆libmylib和路径AB,即

 -L/A -L/B lmylib

它尝试按以下顺序打开库:

A/libmylib.so
A/libmylib.a
B/libmylib.so
B/libmylib.a

因此,如果文件A只有一个静态版本,则使用此静态版本(无论folder中是否有共享版本B)。

因为真正使用哪个库是非常不透明的-它取决于您的系统设置,因此通常会通过以下方式打开链接器的日志记录-Wl,-verbose以进行故障排除。

通过使用该选项,-Bstatic可以强制使用库的静态版本:

gcc  foo.o -L/path -Wl,-Bstatic -lpython3.x -Wl,-Bdynamic <other libs>  -Wl,-verbose -o foo

值得注意的是:

现在:

 gcc <cflags> L/paths foo.c -Wl,-Bstatic -lpython3.X -Wl,-Bdynamic <other libs> -o foo -Wl,-verbose
...
attempt to open path/libpython3.6m.a succeeded
...
ldd foo shows no dependency on python-lib
./foo
It works!

是的,如果您针对静态链接glibc(我不推荐),则需要-Xlinker -export-dynamic从命令行中删除

编译为不带的可执行文件-Xlinker -export-dynamic将无法加载某些c-extension,这取决于将它们加载到的可执行文件的此属性ldopen

python 2022/1/1 18:33:05 有217人围观

撰写回答


你尚未登录,登录后可以

和开发者交流问题的细节

关注并接收问题和回答的更新提醒

参与内容的编辑和改进,让解决方法与时俱进

请先登录

推荐问题


联系我
置顶