【发布时间】:2021-07-27 00:48:36
【问题描述】:
我有一个纯 Python 脚本,我想将它分发到具有未知 Python 配置的系统。因此,我想将 Python 代码编译为独立的可执行文件。
我运行cython --embed ./foo.py 没有问题给foo.c。然后,我跑
gcc $(python3-config --cflags) $(python3-config --ldflags) ./foo.c
python3-config --cflags 给出的地方
-I/usr/include/python3.5m -I/usr/include/python3.5m -Wno-unused-result -Wsign-compare -g -fdebug-prefix-map=/build/python3.5-MLq5fN/python3.5-3.5.3=. -fstack-protector-strong -Wformat -Werror=format-security -DNDEBUG -g -fwrapv -O3 -Wall -Wstrict-prototypes
而python3-config --ldflags 给了
-L/usr/lib/python3.5/config-3.5m-x86_64-linux-gnu -L/usr/lib -lpython3.5m -lpthread -ldl -lutil -lm -Xlinker -export-dynamic -Wl,-O1 -Wl,-Bsymbolic-functions
这样我获得了一个运行没有问题的动态链接的可执行文件。 ldd a.out 收益
linux-vdso.so.1 (0x00007ffcd57fd000)
libpython3.5m.so.1.0 => /usr/lib/x86_64-linux-gnu/libpython3.5m.so.1.0 (0x00007fda76823000)
libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007fda76603000)
libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007fda763fb000)
libutil.so.1 => /lib/x86_64-linux-gnu/libutil.so.1 (0x00007fda761f3000)
libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007fda75eeb000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fda75b4b000)
libexpat.so.1 => /lib/x86_64-linux-gnu/libexpat.so.1 (0x00007fda7591b000)
libz.so.1 => /lib/x86_64-linux-gnu/libz.so.1 (0x00007fda756fb000)
/lib64/ld-linux-x86-64.so.2 (0x00007fda77103000)
现在,我尝试将选项 -static 添加到 gcc,但这会导致错误:
/usr/bin/ld: dynamic STT_GNU_IFUNC symbol `strcmp' with pointer equality in `/usr/lib/gcc/x86_64-linux-gnu/6/../../../x86_64-linux-gnu/libc.a(strcmp.o)' can not be used when making an executable; recompile with -fPIE and relink with -pie
collect2: error: ld returned 1 exit status
我检查了 ldd 提供的所有共享库也安装为静态库。
那么,这是否与 python3-config 提供的选项有些不兼容?
【问题讨论】:
-
真的猜到
-export-dynamic看起来像个嫌疑人? -
-export-dynamic是关于“动态符号表”(根据 gcc 文档)。我不知道这是什么。无论如何,删除它会产生一个错误:/usr/bin/ld: unrecognized option '-Wl,-O1'。 gcc 将不再识别-Wl选项。但是,如果没有这些,我会得到File format not recognized。 -
我认为
-Xlinker -export-dynamicisone 标志 - (XLinker 将标志转发给链接器)尝试整体删除? -
确实可以删除这两个标志。它提供了一个正常运行的可执行文件。但是,添加
-static会导致大量undefined reference to 'PyObject_Call'类型的错误。 -
你的链接器命令行是什么样的?
foo.o应该出现在静态链接库之前。