解决setup.py编译C++代码的-Wstrict-prototypes警告

在利用setuptoolsExtension来编译C++代码时,会出现以下警告:

$ python setup.py bdist_wheel
running bdist_wheel
running build
running build_py
creating build
...
running build_ext
building '_example' extension
...
gcc -pthread -Wno-unused-result -Wsign-compare -DNDEBUG -g -fwrapv -O3 -Wall -Wstrict-prototypes -fPIC ...
cc1plus: warning: command line option ‘-Wstrict-prototypes’ is valid for C/ObjC but not for C++
g++ -pthread -shared ...
...

这个cc1plus: warning:的警告在用g++时不会出现,只有在使用gcc时出现,通常与带--c++参数的SWIG伴生。 虽然忍忍也就过了,但为了零警告的目标,还是需要解决一下。

原因

setuptoolsExtension,源于distutils,是标准库里就有的问题。

在Python的相关配置文件(以Python 3.5为例)/usr/lib/python3.5/config-3.5m-x86_64-linux-gnu/Makefile中,有以下配置:

# Compiler options
OPT=		-DNDEBUG -g -fwrapv -O2 -Wall -Wstrict-prototypes

这里就给gcc默认加上了-Wstrict-prototypes参数,而它在编译C++代码时是多余的。

解决方案

直接用root权限修改配置文件,当然是一个办法,也当然不推荐。 而Extension仅仅是一个指定参数的类,只能添加额外参数,无法修改既有的编译参数。 因此,需要对build_ext进行封装修改,并且替换setup.pybuild_ext子命令。

from setuptools import setup
from setuptools.command.build_ext import build_ext


# Avoid a gcc warning below:
# cc1plus: warning: command line option ‘-Wstrict-prototypes’ is valid
# for C/ObjC but not for C++
class BuildExt(build_ext):
    def build_extensions(self):
        self.compiler.compiler_so.remove('-Wstrict-prototypes')
        super(BuildExt, self).build_extensions()

setup(
    ...
    cmdclass={'build_ext': BuildExt},
    ...
)

参考

这个问题目前的有效参考,基本上只有stackoverflow.com/questions/8106258。 其中还提到了修改环境变量OPT的方法,经测试无效。 在distutils.sysconfig.customize_compiler中有以下代码,应该预示着这个方案只有在设置了CFLAGS才生效吧。

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

        ...
        if 'CFLAGS' in os.environ:
            cflags = opt + ' ' + os.environ['CFLAGS']
            ldshared = ldshared + ' ' + os.environ['CFLAGS']

虽然已经有了一个distutils的方案, 但我还是添加了自己基于Python3的setuptools方案


相关笔记