栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 面试经验 > 面试问答

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

面试问答 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

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

遇到的问题显然来自链接器(gcc在后台启动了一个链接器,看到它-只需

-v
以详细模式启动gcc-
)。因此,让我们从简短的提醒开始,说明链接过程的工作原理:

链接器保留需要解析的所有符号的名称。一开始它只是符号

main
。链接器检查库时会发生什么?

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

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

例如,如果您链​​接:

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
和路径
A
B
,即

 -L/A -L/B lmylib

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

A/libmylib.soA/libmylib.aB/libmylib.soB/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

值得注意的是:

  1. foo.o
    在库之前链接。
  2. 直接在python-library之后关闭静态模式,以便动态链接其他库。

现在:

 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./fooIt works!

是的,如果您针对静态链接

glibc
(我不推荐),则需要
-Xlinker -export-dynamic
从命令行中删除。

编译为不带的可执行文件

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



转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/640951.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号