Je construis une extension C++ pour une utilisation en Python. Je vois cet avertissement généré pendant le processus de compilation - lorsqu'un type:
python setup.py build_ext -i
Quelle est la cause, et comment puis-je résoudre ce problème?
BTW, voici une copie de mon fichier d'installation:
#!/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"],
)
J'utilise gcc 4.4.3 sur Ubuntu
Je peux répondre à une partie de la question, pourquoi vous recevez le message.
Quelque chose dans votre processus de construction appelle gcc sur un fichier source C++ avec l'option -Wstrict-prototypes
. Pour C et Objective-C, le compilateur est donc averti des déclarations de fonction de style ancien qui ne déclarent pas les types d'arguments.
Pour C++, cette option n'a pas de sens. de telles déclarations ne sont même pas autorisées par la langue (les prototypes sont obligatoires).
(Je ne sais pas pourquoi le message mentionne Ada; -Wstrict-prototypes
est encore moins logique pour Ada que pour C++. Ce n'est pas une grosse affaire, mais j'ai soumis ce rapport de bogue , marqué comme étant RÉSOLU/FIXE à partir de 2015 -12-06.)
La solution devrait être de supprimer l'option -Wstrict-prototypes
de l'appel de gcc. Mais comme vous n'invoquez pas directement gcc, il est difficile de savoir comment le faire.
J'ai pu reproduire l'avertissement à l'aide de votre setup.py
, après avoir créé manuellement un fichier factice 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++
...
C'est donc probablement un bug mineur dans le build_ext
de Python.
Mais comme ce n’est qu’un avertissement, pas une erreur fatale, je dirais que vous pouvez l’ignorer en toute sécurité. gcc met en garde sur l'option sans signification, mais ensuite, il l'ignore.
MODIFIER:
En regardant à travers les sources Python-2.7.2, cette section de configure.in
pourrait être le coupable:
case $GCC in
yes)
if test "$CC" != 'g++' ; then
STRICT_PROTO="-Wstrict-prototypes"
fi
(Je suppose que cela est invoqué lors de l'utilisation de build_ext
.)
Il active l'option -Wstrict-prototypes
uniquement si le compilateur est non invoqué en tant que g++
- mais dans votre cas, il utilise la commande gcc
pour compiler le code source C++. Et dans Lib/distutils/command/build_ext.py
, build_extension()
ne fait pas attention à la langue du fichier source lors de l'appel de self.compiler.compile()
, mais uniquement lors de l'appel de self.compiler.link_shared_object()
. (Cela semble étrange; pour les compilateurs autres que gcc, vous ne seriez pas nécessairement en mesure d'utiliser la même commande pour compiler C et C++ - et il est plus logique d'utiliser la commande g++
de toute façon, même si vous ne liez pas. )
MISE À JOUR: Un rapport de bogue Python a été soumis: https://bugs.python.org/issue9031 , et clôturé comme une copie de celui-ci: https://bugs.python.org/issue1222585 , qui est toujours ouvert au moment où j'écris ceci.
Mais comme je l'ai dit, ce n'est qu'un avertissement et vous pouvez probablement l'ignorer en toute sécurité. Les responsables de Python peuvent peut-être utiliser les informations ci-dessus pour résoudre le problème dans une version ultérieure.
Supprimer les prototypes -Wstrict de la variable d'environnement OPT n'a aucun effet. Ce qui fonctionne est de sous-classer build_ext
comme suit:
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)
puis utilisez my_build_ext
dans la fonction setup
:
setup(cmdclass = {'build_ext': my_build_ext})
L'option -Wstrict-prototypes
est lue par distutils à partir de /usr/lib/pythonX.Y/config/Makefile
dans la variable OPT. Cela semble hackish, mais vous pouvez le remplacer en définissant os.environ['OPT']
dans votre fichier setup.py.
Voici un code qui ne semble pas trop nuisible:
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'
)
Le fragment de code suivant dans setup.py supprimera toutes les instances de cet indicateur embêtant:
# 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", "")
# ==================================
Ceci est une solution Python 3.x avec setuptools.
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},
...
)
Plus précisément, distutils utilise les mêmes options que celles construites avec python. Vous pouvez ajouter des options en utilisant extra_compile_args
pour créer le distutils.core.Extension
, mais il ne semble pas y avoir de moyen de supprimer les arguments existants dans gcc ou distutils.
Voir http://bugs.python.org/issue9031 pour plus de détails, il a été clôturé comme un duplicata de http://bugs.python.org/issue1222585 , mais 9031 détaille cet aspect de la problème
Pour ceux qui arriveraient ici après avoir essayé d’installer pydoop sous pypy, cette solution a été adoptée dans 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
interrompt l'installation sous pypy car pypy sysconfig ne fournit pas la variable 'OPT' du tout, ce qui provoque son abandon lors de la tentative d'application de strip () sur None La solution consiste simplement à commenter l'ensemble du bloc.