【问题标题】:cc1plus: warning: command line option "-Wstrict-prototypes" is valid for Ada/C/ObjC but not for C++cc1plus:警告:命令行选项“-Wstrict-prototypes”对 Ada/C/ObjC 有效,但对 C++ 无效
【发布时间】:2011-12-27 17:18: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

【问题讨论】:

    标签: c++ python gcc swig


    【解决方案1】:

    我可以回答部分问题,为什么你会收到这条消息。

    在您的构建过程中使用选项-Wstrict-prototypes 在 C++ 源文件上调用 gcc。对于 C 和 Objective-C,这会导致编译器警告未声明参数类型的旧式函数声明。

    对于 C++,这个选项没有意义;语言甚至不允许这样的声明(原型是强制性的)。

    (我不知道为什么消息提到了 Ada;-Wstrict-prototypes 对 Ada 的意义比对 C++ 的意义还要小。这不是什么大不了的事,但我已经提交了 this bug report,标记为 RESOLVED/FIXED 2015-12-06。)

    解决方案应该是从 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 中的一个小错误。

    但由于这只是一个警告,而不是致命错误,我会说你可以放心地忽略它。 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 维护者可以使用上述信息在未来的版本中修复该问题。

    【讨论】:

    • 现在这是一些非常好的探索!感谢您不厌其烦地嗅出它。我会把它提交给 Python 维护者。
    • @HomunculusReticulli:很酷,如果您收到任何反馈,请在此处跟进。
    • @HomunculusReticulli:仅供参考,我已经报告了一个针对 gcc 的错误,因为 Ada 接受了该选项(这与当前问题没有直接关系)。 gcc.gnu.org/bugzilla/show_bug.cgi?id=51115
    • @HomunculusReticulli:我的 gcc 错误报告在 2015 年 12 月 6 日被标记为 RESOLVED/FIXED
    • 作为参考,有一个针对此错误issue9031 的 python 票证,它重定向到更一般的 distutils 和 C++ 问题:issue1222585
    【解决方案2】:

    更具体地说,distutils 使用与构建 python 相同的选项,您可以在创建 distutils.core.Extension 时使用 extra_compile_args 添加选项,但似乎没有办法删除 gcc 或 distutils 中的现有参数。

    详情见http://bugs.python.org/issue9031,它已作为http://bugs.python.org/issue1222585的副本关闭,但9031详细说明了这方面的问题

    【讨论】:

      【解决方案3】:

      -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'
      )
      

      【讨论】:

        【解决方案4】:

        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", "")
        # ==================================
        

        【讨论】:

          【解决方案5】:

          为了任何人在尝试在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 时中止。解决方案就是注释掉整个块。

          【讨论】:

            【解决方案6】:

            从 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,fwiw。
            • 不确定是否需要 customize_compiler 调用或 try/except。
            • try catch 块确保它仍然适用于 Windows 等使用没有 compiler_so 属性的 MSVCCompiler 的操作系统。
            【解决方案7】:

            这是一个带有 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},
                ...
            )
            

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 2013-12-09
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2016-12-11
              • 2018-05-26
              • 2016-08-10
              相关资源
              最近更新 更多