如何在编译Python模块扩展时静态链接库
我想修改一个setup.py文件,让命令“python setup.py build”能够编译一个基于C的扩展模块,并且这个模块是静态链接到一个库,而不是动态链接。
目前,这个扩展是动态链接到多个库的。我希望除了静态链接到一个库之外,其他的都不变。我已经成功地通过手动修改distutils运行的gcc命令来实现了这一点,不过这需要我明确列出所有依赖的库。
也许这信息有点多,但为了清楚起见,这里是“python setup.py build”脚本执行时的最终链接命令:
gcc -pthread -shared -L/system/lib64 -L/system/lib/ -I/system/include build/temp.linux-x86_64-2.7/src/*.o -L/system/lib -L/usr/local/lib -L/usr/lib -ligraph -o build/lib.linux-x86_64-2.7/igraph/core.so
这是我手动修改的内容:
gcc -pthread -shared -L/system/lib64 -L/system/lib/ -I/system/include build/temp.linux-x86_64-2.7/src/*.o -L/system/lib -L/usr/local/lib -L/usr/lib /system/lib/libigraph.a -lxml2 -lz -lgmp -lstdc++ -lm -ldl -o build/lib.linux-x86_64-2.7/igraph/core.so
在分发Python模块的第2.3.4节中讨论了库的规范,但只有“library_dirs”是合适的,而这些库是动态链接的。
我在Linux环境下进行开发,但这个包也会在Windows上编译和安装,所以我希望找到一个可移植的解决方案。
有人能告诉我在哪里可以找到相关的说明,或者如何修改setup.py脚本吗?(提前谢谢!)
我刚刚加入StackOverflow,如果我没有正确标记这个问题,或者在发布中犯了其他错误,我深感抱歉。
3 个回答
这个有可能会有效吗?
g++ -Wl,-Bstatic -lfoo -Wl,-Bdynamic -lbar -Wl,--as-needed
六七年过去了,关于如何在Python扩展中使用静态链接的文档还是很少。正如提问者在评论中提到的,这个用法跟操作系统有关。
在Linux / Unix上
静态库的链接方式和目标文件一样,应该把它的路径和扩展名放到extra_objects
里。
在Windows上
编译器会判断链接的库是静态库还是动态库,静态库的名字会放到库列表中,而目录则放到library_dir里。
两个平台的解决方案
在下面的例子中,我会用提问者的库场景,链接静态的igraph
和动态的z
、xml2
和gmp
。这个解决方案有点小技巧,但至少在每个平台上都能正确工作。
static_libraries = ['igraph']
static_lib_dir = '/system/lib'
libraries = ['z', 'xml2', 'gmp']
library_dirs = ['/system/lib', '/system/lib64']
if sys.platform == 'win32':
libraries.extend(static_libraries)
library_dirs.append(static_lib_dir)
extra_objects = []
else: # POSIX
extra_objects = ['{}/lib{}.a'.format(static_lib_dir, l) for l in static_libraries]
ext = Extension('igraph.core',
sources=source_file_list,
libraries=libraries,
library_dirs=library_dirs,
include_dirs=include_dirs,
extra_objects=extra_objects)
在MacOS上
我猜这个方法在MacOS上也能用(使用else
路径),但我没有测试过。
如果其他方法都不行,还有一个不太常见的选项,就是在 extra_compile_args
和 extra_link_args
中设置一些额外的编译和链接参数,这些都是给 Extension
构建器用的。(你也可以在 这里 找到更多信息。)
不过,你可能需要写一些和操作系统相关的代码,以便为特定的平台获取正确的参数格式。