如何覆盖setup.py默认使用的GCC编译器标志?

76 投票
3 回答
41444 浏览
提问于 2025-04-16 22:48

我了解到,setup.py 文件使用的是构建 Python 时用的相同的 CFLAGS。我有一个我们的 C 扩展出现了段错误(segfault)。我需要构建它时不使用 -O2,因为 -O2 会优化掉一些值和代码,导致核心文件不足以帮助我找到问题所在。

我只需要修改 setup.py,让它不使用 -O2

我看过 distutils 的文档,特别是 distutils.ccompilerdistutils.unixccompiler,知道怎么添加标志、库和包含文件,但不知道怎么修改默认的 GCC 标志。

具体来说,这是针对一个使用 Python 2.5.1 的旧产品,里面有很多回退(backports)(是的,Fedora 8,我知道...)。不,我不能更改操作系统或 Python 版本,也不能在没有很大问题的情况下重新编译 Python。我只需要为一个客户构建这个 C 扩展,因为只有他们的环境出现了段错误。

3 个回答

4

distutilssetuptools是Python中用来创建和管理扩展模块的工具。它们允许你在setup.py脚本中通过extra_compile_argsextra_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
8

我遇到了一个问题,想要完全去掉一个标志(-pipe),这样我才能在内存较小的系统上编译SciPy。我发现有个小技巧,就是可以通过编辑这个文件:/usr/lib/pythonN.N/_sysconfigdata.py,来删除所有出现的那个标志,其中N.N是你的Python版本。这个文件里有很多重复的地方,我不太确定哪些是setup.py真正用到的。

89
  • 在运行 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
    

撰写回答