【问题标题】:Where are these extra compiler flags coming from when using setup.py to compile a Cython extension?使用 setup.py 编译 Cython 扩展时,这些额外的编译器标志来自哪里?
【发布时间】:2020-07-27 06:14:06
【问题描述】:

我正在尝试编译一个简单的小 hello world 示例来感受 Cython。它可以工作,但是编译中到处都是我不想要的标志。按照示例here,我能够清除大部分不需要的标志,但尽管我尽最大努力控制环境变量,但仍有一些标志仍然存在。链接问题中的最后一条评论表明额外的标志可能由供应商烘焙到编译器中,但我已经通过使用几个不同的编译器验证了这不太可能,所有这些编译器都默认使用相同的额外标志。

我对 setup.py 的调用如下所示:

CC="gcc" CXX="g++" OPT="" CFLAGS="-O3 -D_GNU_SOURCE" BASECFLAGS="" LDFLAGS="" CCSHARED="" LDSHARED="gcc -shared" PY_CORE_FLAGS="" PY_CFLAGS="" AR="" ARFLAGS="" CPPFLAGS="" CPP="" SHLIB_SUFFIX="" python3 setup.py build_ext --inplace

setup.py 很简单:

from setuptools import Extension, setup
from Cython.Build import cythonize

setup(
    ext_modules = cythonize([Extension("hellotest", ["hellotest.pyx"])], language_level="3")
)

最后是编译过程中 gcc 的输出,不需要的标志括在方括号中:

gcc [-DNDEBUG -g -fwrapv -O2 -Wall] -O3 -D_GNU_SOURCE -fPIC -I./ -I. -I/usr/include/python3.6m -c hellotest.c -o build/temp.linux-x86_64-3.6/hellotest.o
gcc [-DNDEBUG -g -fwrapv -O2 -Wall] -O3 -D_GNU_SOURCE -fPIC -I./ -I. -I/usr/include/python3.6m -c ./funcs.c -o build/temp.linux-x86_64-3.6/./funcs.o
gcc -shared -O3 -D_GNU_SOURCE build/temp.linux-x86_64-3.6/hellotest.o build/temp.linux-x86_64-3.6/./funcs.o -o build/lib.linux-x86_64-3.6/hellotest.cpython-36m-x86_64-linux-gnu.so

有没有人知道他们在哪里找到了编译器选项?

【问题讨论】:

  • 我添加了一个“setuptools”,因为我很确定这些标志是由 setuptools 添加的。我不知道确切的位置,但希望添加标签能将问题摆在这样做的人面前。

标签: c python-3.x cython setuptools setup.py


【解决方案1】:

Setuptools 继承了distutils 的许多功能,其中之一就是找出用于构建 c 扩展的 cflags。

build_ext 命令运行时,它会调用distutils.sysconfig.customize_compiler(),而后者又会调用distutils.sysconfig.get_config_vars()

def customize_compiler(compiler):
    ...
        (cc, cxx, cflags, ccshared, ldshared, shlib_suffix, ar, ar_flags) = \
            get_config_vars('CC', 'CXX', 'CFLAGS',
                            'CCSHARED', 'LDSHARED', 'SHLIB_SUFFIX', 'AR', 'ARFLAGS')
   ...

获取默认的 cflags,稍后将通过值 from the CFLAGS-environment variable 以及来自 setup-file 和 passed to the compiler 的值进行扩展。

get_config_vars() 解析(至少在 Linux 上)makefile 和 config-header,即 pyconfig.h,从而获取构建当前 Python 可执行文件的 cflags(以及其他内容)。然后使用相同的 cflags 来构建扩展。

如果需要,可以操纵这些内置标志,例如我在此SO-post 中所展示的。这样做是否明智是另一个问题。


这在 Windows 上有点微妙,get_config_vars() 没有提供那么多信息 - 因此使用其他技巧来构建正确的选项(例如,参见 SO-post)。

【讨论】:

  • 那么我可能会问另一个问题。虽然 -DNDEBUG 和 -g 都是默认值,但这似乎很奇怪,我会假设它们有冲突。
  • @KBringgs 没有冲突:-g 表示调试信息包含在生成的工件中。包括它意味着结果更大(但不是很慢),所以通常它不是在发布模式下完成的。但是我更喜欢 Anaconda-distribution,因为他们使用 -g 构建了它:当这些信息在手边时,使用分析器或使用调试器环顾四周会容易得多。 -DNDEBUG 表示 assert(C 函数)没有被执行,这是在发布模式下通常希望的。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-06-06
  • 1970-01-01
  • 1970-01-01
  • 2018-05-25
  • 2015-01-09
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多