cc1plus: 警告:命令行选项 "-Wstrict-prototypes" 对Ada/C/ObjC有效,但对C++无效

44 投票
7 回答
45011 浏览
提问于 2025-04-17 06:10

我正在为Python开发一个C++扩展。在编译的过程中,我看到出现了一个警告,警告是关于某个类型的:

python setup.py build_ext -i

这个警告是怎么产生的,我该怎么解决呢?

顺便说一下,这是我的设置文件的内容:

#!/usr/bin/env python

    """
    setup.py file for SWIG example
    """

    from distutils.core import setup, Extension


    example_module = Extension('_foolib',
                               sources=['example_wrap.cxx', 
                                        '../wrapper++/src/Foo.cpp'
                                       ],
                               libraries=["foopp"]
                               )

    setup (name = 'foolib',
           version = '0.1',
           author      = "Me, Myself and I",
           description = """Example""",
           ext_modules = [example_module],
           py_modules = ["example"],
           )

我在Ubuntu上使用的是gcc 4.4.3版本。

7 个回答

14

-Wstrict-prototypes 这个选项是从 /usr/lib/pythonX.Y/config/Makefile 文件中被 distutils 读取的,它是 OPT 变量的一部分。虽然这看起来有点不太正规,但你可以通过在你的 setup.py 文件中设置 os.environ['OPT'] 来覆盖它。

下面是一段看起来没什么害处的代码:

import os
from distutils.sysconfig import get_config_vars

(opt,) = get_config_vars('OPT')
os.environ['OPT'] = " ".join(
    flag for flag in opt.split() if flag != '-Wstrict-prototypes'
)
24

从OPT环境变量中去掉-Wstrict-prototypes这个选项没有任何效果。有效的方法是像下面这样对build_ext进行子类化:

from distutils.command.build_ext import build_ext
from distutils.sysconfig import customize_compiler

class my_build_ext(build_ext):
    def build_extensions(self):
        customize_compiler(self.compiler)
        try:
            self.compiler.compiler_so.remove("-Wstrict-prototypes")
        except (AttributeError, ValueError):
            pass
        build_ext.build_extensions(self)

然后在setup函数里面使用my_build_ext

setup(cmdclass = {'build_ext': my_build_ext})
46

我可以回答你问题的一部分,告诉你为什么会收到这个消息。

在你的构建过程中,有某个地方在用 gcc 编译一个 C++ 源文件,并且加上了 -Wstrict-prototypes 这个选项。对于 C 和 Objective-C,这个选项会让编译器警告你使用了旧式的函数声明,因为这些声明没有说明参数的类型。

但是对于 C++ 来说,这个选项就没有意义了;因为这种声明在语言中根本是不允许的(函数原型是必须的)。

(我不知道为什么消息中提到 Ada;对 Ada 来说,-Wstrict-prototypes 的意义比对 C++ 还要小。这不是大问题,但我已经提交了一个错误报告,在 2015-12-06 标记为已解决/修复。)

解决办法应该是把 -Wstrict-prototypes 这个选项从 gcc 的调用中去掉。但是因为你并不是直接调用 gcc,所以很难知道该怎么做。

我用你的 setup.py 复现了这个警告,手动创建了一个虚拟的 example_wrap.cxx 文件:

% python setup.py build_ext -i
running build_ext
building '_foolib' extension
gcc -pthread -fno-strict-aliasing -DNDEBUG -g -fwrapv -O2 -Wall -Wstrict-prototypes -fPIC -I/usr/include/python2.7 -c example_wrap.cxx -o build/temp.linux-i686-2.7/example_wrap.o
cc1plus: warning: command line option "-Wstrict-prototypes" is valid for Ada/C/ObjC but not for C++
...

所以这可能是 Python 的 build_ext 中的一个小错误。

不过因为这只是一个警告,而不是致命错误,我觉得你可以安全地忽略它。gcc 会警告这个没意义的选项,但之后它会直接忽略它。

编辑

查看 Python-2.7.2 的源代码,这部分 configure.in 可能是罪魁祸首:

case $GCC in
yes)
    if test "$CC" != 'g++' ; then
        STRICT_PROTO="-Wstrict-prototypes"
    fi

(我假设这是在使用 build_ext 时调用的。)

它只有在编译器不是以 g++ 的方式调用时,才会开启 -Wstrict-prototypes 这个选项——但在你的情况下,它是用 gcc 命令来编译 C++ 源代码的。而在 Lib/distutils/command/build_ext.py 中,build_extension() 在调用 self.compiler.compile() 时并没有关注源文件的语言,只有在调用 self.compiler.link_shared_object() 时才会关注。(这听起来有点奇怪;对于除了 gcc 以外的编译器,你可能不能用同一个命令来编译 C 和 C++——而且即使不链接,使用 g++ 命令也更合理。)

更新:已经提交了一个 Python 的错误报告:https://bugs.python.org/issue9031,并且被关闭为这个报告的重复:https://bugs.python.org/issue1222585,在我写这段话的时候这个报告仍然是开放状态。

但正如我所说,这只是一个警告,你可能可以安全地忽略它。也许 Python 的维护者可以利用以上信息在未来的版本中修复这个问题。

撰写回答