如何用distutils/setuptools简便编译链接Cython生成的C文件为可执行文件?
用distutils/setuptools编译链接Cython生成的C文件为可执行文件
你可以直接使用distutils内置的CCompiler类完成编译和链接操作,它会自动适配当前系统的编译器(Windows下的cl、Linux下的gcc等),无需手动指定路径或系统专属参数,和cythonize的适配逻辑完全一致。以下是最基础的编译链接原语用法:
1. 编译单个C文件为目标文件
通过CCompiler的compile方法可将单个C文件编译成目标文件(Windows为.obj,Linux为.o):
import distutils.ccompiler import os # 创建编译器实例,自动适配当前系统 compiler = distutils.ccompiler.new_compiler() # 编译指定C文件,返回生成的目标文件路径 c_file = "cython_generated.c" obj_file = compiler.compile([c_file])[0] print(f"生成目标文件: {obj_file}")
2. 链接多个目标文件为可执行文件
用同一个编译器实例调用link_executable方法,将多个目标文件(包括Cython生成的和自定义C代码的目标文件)链接成可执行文件:
import sysconfig # 获取Python头文件和库路径(Cython生成的C文件依赖Python运行时) include_dirs = [sysconfig.get_path("include")] library_dirs = [sysconfig.get_path("platstdlib")] # 适配不同Python版本的库名称 py_version = sysconfig.get_config_var("VERSION") libraries = [f"python{py_version}" + sysconfig.get_config_var("ABIFLAGS")] # 待链接的目标文件列表 obj_files = [obj_file, "utils.o"] # 假设还有一个自定义utils.c编译出的目标文件 # 根据系统设置可执行文件名称 executable_name = "my_program.exe" if os.name == "nt" else "my_program" # 链接生成可执行文件 compiler.link_executable( obj_files, executable_name, include_dirs=include_dirs, library_dirs=library_dirs, libraries=libraries ) print(f"生成可执行文件: {executable_name}")
完整示例脚本
把编译和链接逻辑整合到一个脚本,直接运行即可完成操作:
import distutils.ccompiler import os import sysconfig def compile_c_to_obj(c_file): compiler = distutils.ccompiler.new_compiler() return compiler.compile([c_file])[0] def link_objs_to_executable(obj_files, exec_name): compiler = distutils.ccompiler.new_compiler() include_dirs = [sysconfig.get_path("include")] library_dirs = [sysconfig.get_path("platstdlib")] py_version = sysconfig.get_config_var("VERSION") libraries = [f"python{py_version}" + sysconfig.get_config_var("ABIFLAGS")] compiler.link_executable( obj_files, exec_name, include_dirs=include_dirs, library_dirs=library_dirs, libraries=libraries ) if __name__ == "__main__": # 编译Cython生成的C文件 cython_obj = compile_c_to_obj("my_cython_module.c") # 编译自定义辅助C文件(可选) utils_obj = compile_c_to_obj("utils.c") # 链接成可执行文件 exec_name = "my_app.exe" if os.name == "nt" else "my_app" link_objs_to_executable([cython_obj, utils_obj], exec_name)
关键说明
new_compiler()会自动检测当前系统的编译器,无需手动指定cl或gcc的路径。- 通过
sysconfig获取Python的头文件和库路径,避免手动配置Python依赖,跨平台通用。 - 该方式完全基于distutils的基础API,没有setup.py的复杂配置逻辑,仅适用于当前开发机器的编译需求。
内容的提问来源于stack exchange,提问作者Ruediger Jungbeck
相关产品推荐
相关产品推荐

