如何在通过setup.py编译Python扩展时移除特定编译器标志?
如何从Python扩展的编译标志中移除默认的特定选项?
我用python3 setup.py build构建Python扩展时,命令会先使用Python默认的所有编译器标志,再追加我在extra_compile_flags里指定的自定义标志。现在我想彻底移除几个特定的默认标志:
-Wp,-D_FORTIFY_SOURCE=2-fstack-protector-strong-Wstrict-prototypes
目前我是在extra_compile_flags里追加否定标志来抵消它们:
-Wp,-U_FORTIFY_SOURCE-fstack-protector-explicit-Wno-strict-prototypes
但我更希望这些默认标志从一开始就不出现,有没有标准的实现方式?
标准实现方法
当然可以直接移除这些默认标志,核心思路是在setup.py中直接修改编译器的默认标志列表,而非用否定选项抵消。以下是两种常用的可行方式:
1. 直接修改distutils配置变量
这是最简洁的方案,通过修改distutils的全局配置变量,直接剔除不需要的默认标志:
from distutils.core import setup, Extension from distutils.sysconfig import get_config_vars # 获取默认编译标志并过滤 opt = get_config_vars('OPT')[0] unwanted_flags = ['-Wp,-D_FORTIFY_SOURCE=2', '-fstack-protector-strong', '-Wstrict-prototypes'] for flag in unwanted_flags: opt = opt.replace(flag, '') # 更新配置 get_config_vars()['OPT'] = opt # 定义并构建扩展 my_ext = Extension('my_extension', sources=['my_ext.c']) setup( name='my_extension', ext_modules=[my_ext] )
2. 自定义编译器类实现深度过滤
如果需要更灵活的编译流程控制,可以继承默认编译器类,重写编译方法来过滤标志:
from distutils.core import setup, Extension from distutils.unixccompiler import UnixCCompiler from distutils.command.build_ext import build_ext class CustomCompiler(UnixCCompiler): def compile(self, sources, output_dir=None, macros=None, include_dirs=None, debug=0, extra_preargs=None, extra_postargs=None, depends=None): # 过滤掉不需要的默认标志 filtered_postargs = [] if extra_postargs: filtered_postargs = [arg for arg in extra_postargs if arg not in ['-Wp,-D_FORTIFY_SOURCE=2', '-fstack-protector-strong', '-Wstrict-prototypes']] # 调用父类编译方法 return super().compile(sources, output_dir, macros, include_dirs, debug, extra_preargs, filtered_postargs, depends) class CustomBuildExt(build_ext): def build_extensions(self): self.compiler = CustomCompiler(compiler=self.compiler.compiler_type) super().build_extensions() # 执行构建 setup( name='my_extension', ext_modules=[Extension('my_extension', sources=['my_ext.c'])], cmdclass={'build_ext': CustomBuildExt} )
注意事项
- 第一种方案适合大多数常规场景,代码简洁易维护;第二种方案适合需要深度定制编译逻辑的场景。
- 不同平台(如Linux、macOS)的默认编译标志可能存在差异,测试时需适配目标环境。
- 部分默认标志(如
-fstack-protector-strong)属于安全加固选项,移除前请确认业务场景的必要性。
内容的提问来源于stack exchange,提问作者Mikhail T.
相关产品推荐
相关产品推荐

