如何覆盖setup.py默认使用的GCC编译器标志?
我了解到,setup.py
文件使用的是构建 Python 时用的相同的 CFLAGS
。我有一个我们的 C 扩展出现了段错误(segfault)。我需要构建它时不使用 -O2
,因为 -O2
会优化掉一些值和代码,导致核心文件不足以帮助我找到问题所在。
我只需要修改 setup.py
,让它不使用 -O2
。
我看过 distutils
的文档,特别是 distutils.ccompiler
和 distutils.unixccompiler
,知道怎么添加标志、库和包含文件,但不知道怎么修改默认的 GCC 标志。
具体来说,这是针对一个使用 Python 2.5.1 的旧产品,里面有很多回退(backports)(是的,Fedora 8,我知道...)。不,我不能更改操作系统或 Python 版本,也不能在没有很大问题的情况下重新编译 Python。我只需要为一个客户构建这个 C 扩展,因为只有他们的环境出现了段错误。
3 个回答
distutils
和setuptools
是Python中用来创建和管理扩展模块的工具。它们允许你在setup.py
脚本中通过extra_compile_args
和extra_link_args
这两个参数来指定任何编译器或链接器的选项。这些额外的选项会在默认选项之后添加,并且会覆盖之前的任何互斥选项。
不过,通常情况下,这样做并不太有用,因为你通过PyPI发布的包可能会被不同的编译器构建,而这些编译器的选项可能不兼容。
下面的代码可以让你以扩展和编译器特定的方式来指定这些选项:
from setuptools import setup
from setuptools.command.build_ext import build_ext
class build_ext_ex(build_ext):
extra_compile_args = {
'extension_name': {
'unix': ['-O0'],
'msvc': ['/Od']
}
}
def build_extension(self, ext):
extra_args = self.extra_compile_args.get(ext.name)
if extra_args is not None:
ctype = self.compiler.compiler_type
ext.extra_compile_args = extra_args.get(ctype, [])
build_ext.build_extension(self, ext)
setup(
...
cmdclass = {'build_ext': build_ext_ex},
...
)
当然,如果你希望所有扩展使用相同的(但仍然是编译器特定的)选项,你可以简化这个过程。
这里有一个支持的编译器类型列表(可以通过setup.py build_ext --help-compiler
命令查看):
--compiler=bcpp Borland C++ Compiler
--compiler=cygwin Cygwin port of GNU C Compiler for Win32
--compiler=mingw32 Mingw32 port of GNU C Compiler for Win32
--compiler=msvc Microsoft Visual C++
--compiler=unix standard UNIX-style compiler
我遇到了一个问题,想要完全去掉一个标志(-pipe),这样我才能在内存较小的系统上编译SciPy。我发现有个小技巧,就是可以通过编辑这个文件:/usr/lib/pythonN.N/_sysconfigdata.py,来删除所有出现的那个标志,其中N.N是你的Python版本。这个文件里有很多重复的地方,我不太确定哪些是setup.py真正用到的。
在运行
setup.py
之前,先加上CFLAGS="-O0"
:% CFLAGS="-O0" python ./setup.py
这里的
-O0
会在编译的时候加到CFLAGS
里,所以会覆盖之前的-O2
设置。另一种方法是在
setup.py
中的extra_compile_args
添加-O0
:moduleA = Extension('moduleA', ....., include_dirs = ['/usr/include', '/usr/local/include'], extra_compile_args = ["-O0"], )
如果你想去掉所有默认的标志,可以使用:
% OPT="" python ./setup.py