cc1plus: 警告:命令行选项“-Wstrict-prototypes”适用于Ada/C/ObjC,但不适用于C++。

44

我正在为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个回答

46
我可以回答部分问题,为什么你会收到这个消息。
你的构建过程中有些东西正在使用gcc来处理C++源文件,并使用选项-Wstrict-prototypes。对于C和Objective-C,这会导致编译器警告旧式函数声明没有声明参数类型。
对于C ++,该选项是没有意义的;这种声明甚至不被语言允许(原型是强制性的)。 (我不知道为什么消息提到了Ada; -Wstrict-prototypes对Ada来说甚至比对C ++来说都更加无意义。这不是一个很大的问题,但我已经提交了此错误报告,标记为已解决/已修复,截至2015年12月6日。)
解决方法应该是从调用gcc的地方删除-Wstrict-prototypes选项。但由于您不直接调用gcc,因此很难知道如何做。
我能够在手动创建一个虚拟的example_wrap.cxx文件后,使用您的setup.py重现这个警告:
% 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中的一个小bug。

但由于它只是一个警告而不是致命错误,我认为你可以安全地忽略它。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 中,当调用 self.compiler.compile() 时,它并不关心源文件语言,只有在调用 self.compiler.link_shared_object() 时才关心。这似乎很奇怪;对于除了 gcc 之外的编译器,您可能无法使用相同的命令来编译 C 和 C++,而且即使您不链接,使用 g++ 命令也更合理。

更新:有人提交了一个 Python Bug 报告:https://bugs.python.org/issue9031,并将其关闭为此问题的重复项:https://bugs.python.org/issue1222585,我写下这些文字时该问题仍然未解决。

但是,这只是一个警告,您可以安全地忽略它。也许 Python 维护者可以使用上述信息在未来的版本中修复问题。


2
现在这才是一项伟大的勘探工作!感谢您花时间去嗅探它。我会将其提交给Python维护者们。 - Homunculus Reticulli
@HomunculusReticulli:很酷,请在这里跟进您收到的任何反馈。 - Keith Thompson
@HomunculusReticulli:FYI,我已经针对gcc的一个bug进行了报告,因为该选项被接受用于Ada语言(这与当前问题没有直接关系)。http://gcc.gnu.org/bugzilla/show_bug.cgi?id=51115 - Keith Thompson
@HomunculusReticulli:我的gcc错误报告已于2015年12月6日标记为已解决/已修复。 - Keith Thompson
参考文献中有一个关于此错误的 Python 记录 issue9031,该记录会重定向到一个更一般的 distutils 和 C++ 问题:issue1222585 - Cas

24

从OPT环境变量中删除-Wstrict-prototypes没有任何效果。有效的方法是如下所示,子类化build_ext

从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})

谢谢。这正是我在寻找的命令。顺便说一下,它也适用于setuptools。 - Mike Jarvis
不确定是否需要customize_compiler调用或try/except。 - Chris Withers
try catch 块确保在使用 MSVCCompiler 的操作系统(例如 Windows)上仍然可以正常工作,因为该编译器没有 compiler_so 属性。 - kautenja

14

这是一个带有setuptools的Python 3.x解决方案。

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):
        if '-Wstrict-prototypes' in self.compiler.compiler_so:
            self.compiler.compiler_so.remove('-Wstrict-prototypes')
        super().build_extensions()

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

14

-Wstrict-prototypes选项是由distutils从/usr/lib/pythonX.Y/config/Makefile读取的,作为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'
)

13
以下是在 setup.py 中去除所有此烦人标志的代码片段:
# Remove the "-Wstrict-prototypes" compiler option, which isn't valid for C++.
import distutils.sysconfig
cfg_vars = distutils.sysconfig.get_config_vars()
for key, value in cfg_vars.items():
    if type(value) == str:
        cfg_vars[key] = value.replace("-Wstrict-prototypes", "")
# ==================================

2
更具体地说,distutils使用与Python构建时相同的选项,您可以在创建distutils.core.Extension时使用extra_compile_args添加选项,但似乎没有办法删除gcc或distutils中现有的参数。
有关详细信息,请查看http://bugs.python.org/issue9031,它已被关闭为http://bugs.python.org/issue1222585的重复项,但9031详细说明了这个问题的方面。

1
为了那些在尝试在pypy下安装pydoop的人着想,这是在pydoop 1.0.0中采用的解决方案:
from distutils.sysconfig import get_config_var
_UNWANTED_OPTS = frozenset(['-Wstrict-prototypes'])
os.environ['OPT'] = ' '.join(
    _ for _ in get_config_var('OPT').strip().split() if _ not in _UNWANTED_OPTS

在pypy下会导致安装失败,因为pypy sysconfig根本没有提供'OPT'变量,导致当它尝试将strip()应用于None时中止。解决方法只是注释掉整个代码块。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接