Remplacer les indicateurs de compilation pour les fichiers uniques

110

Je voudrais utiliser un ensemble global d'indicateurs pour compiler un projet, ce qui signifie que dans mon fichier CMakeLists.txt de niveau supérieur, j'ai spécifié:

ADD_DEFINITIONS ( -Wall -Weffc++ -pedantic -std=c++0x )

Cependant, pour un fichier spécifique (disons "foo.cpp") dans un sous-répertoire, je veux changer les drapeaux de compilation pour ne pas appliquer -Weffc ++ (bibliothèque commerciale incluse que je ne peux pas changer). Pour simplifier la situation pour n'utiliser que -Wall, j'ai essayé:

 SET_SOURCE_FILES_PROPERTIES( foo.cpp PROPERTIES COMPILE_FLAGS -Wall )
 ADD_EXECUTABLE( foo foo.cpp )

, qui n'a pas fonctionné. J'ai aussi essayé

SET_PROPERTY( SOURCE foo.cpp PROPERTY COMPILE_FLAGS -Wall )
ADD_EXECUTABLE( foo foo.cpp )

et

ADD_EXECUTABLE( foo foo.cpp )
SET_TARGET_PROPERTIES( foo PROPERTIES COMPILE_FLAGS -Wall )

, dans lequel ni l'un ni l'autre n'a fonctionné.

Enfin, j'ai essayé de supprimer cette définition:

REMOVE_DEFINITIONS( -Weffc++ )
ADD_EXECUTABLE( foo foo.cpp )
ADD_DEFINITIONS( -Weffc++ )

, qui ne fonctionnait pas non plus (ce qui signifie que je reçois beaucoup d'avertissements de style concernant la bibliothèque commerciale). (** Remarque: les avertissements SONT supprimés si JE NE ré-inclue PAS la directive -Weffc ++ après la construction de l'exécutable.)

J'ai également essayé de supprimer temporairement les indicateurs de compilation: http://www.cmake.org/pipermail/cmake/2007-June/014614.html , mais cela n'a pas aidé.

N'y a-t-il pas une solution élégante à cela?

JB Marron
la source
1
Attendez, si votre dernière tentative fonctionne, mais seulement après sa construction, cela ne peut-il pas être un problème de mise en cache? Essayez de supprimer CMakeCache après avoir apporté vos modifications.
Cameron
En relation, consultez Comment modifier un indicateur de compilateur pour un seul exécutable dans CMake? La réponse d'André montre ce qui semble être un moyen de remplacer les options existantes par de nouvelles options.
jww

Réponses:

126

Vos tentatives ci-dessus ajoutent d'autres indicateurs à votre fichier / cible au lieu d'écraser comme vous semblez vous y attendre. Par exemple, à partir de la documentation relative aux propriétés sur les fichiers source - COMPILE_FLAGS :

Ces indicateurs seront ajoutés à la liste des indicateurs de compilation lors de la construction de ce fichier source.

Vous devriez pouvoir -Weffc++annuler l' indicateur pour foo.cpp en faisant

set_source_files_properties(foo.cpp PROPERTIES COMPILE_FLAGS -Wno-effc++)

Cela devrait avoir pour effet d'ajouter -Wno-effc++après -Weffc++dans la commande du compilateur, et le dernier paramètre l'emporte. Pour voir la commande complète et vérifier que c'est bien le cas, vous pouvez faire

make VERBOSE=1

En aparté, l' un des mainteneurs de la bibliothèque standard GNU C ++ présente un avis joli négatif sur -Weffc++dans cette réponse .

Un autre point est que vous faites une mauvaise utilisation add_definitionsdans le sens où vous l'utilisez pour les indicateurs de compilateur plutôt que pour les définitions de préprocesseur prévues.

Il serait préférable d'utiliser add_compile_options

add_compile_options(-Wall -Weffc++ -pedantic -std=c++0x)

ou pour les versions de CMake <3.0 pour faire quelque chose de plus comme:

set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Weffc++ -pedantic -std=c++0x")

En réponse à d'autres questions dans les commentaires ci-dessous, je pense qu'il est impossible de supprimer de manière fiable un indicateur sur un seul fichier. La raison en est que pour un fichier source donné, le COMPILE_OPTIONSet 1 de sa cible sont appliqués, mais ceux-ci n'apparaissent dans aucune des propriétés de ce fichier source.COMPILE_FLAGS

Vous pouvez envisager de supprimer l'indicateur de problème de la cible COMPILE_OPTIONS, puis de l'appliquer à chacune des sources de la cible individuellement, en l'omettant du fichier source spécifique si nécessaire.

Cependant, bien que cela puisse fonctionner dans de nombreux scénarios, cela pose quelques problèmes.

Premièrement, les propriétés des fichiers source n'incluent pas COMPILE_OPTIONS, seulement COMPILE_FLAGS. C'est un problème car le COMPILE_OPTIONSd'une cible peut inclure des expressions de générateur , mais COMPILE_FLAGSne les prend pas en charge. Vous devrez donc prendre en compte les expressions du générateur lors de la recherche de votre indicateur, et en fait vous devrez peut-être même "analyser" les expressions du générateur si votre indicateur était contenu dans un ou plusieurs pour voir s'il devrait être réappliqué au reste fichiers source.

Deuxièmement - depuis CMake v3.0, les cibles peuvent spécifier INTERFACE_COMPILE_OPTIONS. Cela signifie qu'une dépendance de votre cible peut ajouter ou remplacer votre cible COMPILE_OPTIONSvia son INTERFACE_COMPILE_OPTIONS. Vous devrez donc en outre parcourir de manière récursive toutes les dépendances de votre cible (ce n'est pas une tâche particulièrement facile puisque la liste des LINK_LIBRARIESpour la cible peut également contenir des expressions de générateur) pour trouver celles qui appliquent l'indicateur de problème, et essayez de la supprimer de celles-ci. cibles » INTERFACE_COMPILE_OPTIONSaussi.

À ce stade de complexité, je chercherais à soumettre un correctif à CMake pour fournir la fonctionnalité permettant de supprimer un indicateur spécifique sans condition d'un fichier source.


1: Notez que contrairement à la COMPILE_FLAGSpropriété sur les fichiers sources, la COMPILE_FLAGSpropriété sur les cibles est obsolète.

Fraser
la source
6
Mais comment définir les indicateurs de compilation pour les fichiers séparément sans les ajouter. Par exemple, je souhaite utiliser des indicateurs de compilation différents pour la cible résultante et pour les fichiers, mais comme ils sont ajoutés, je devrais les supprimer manuellement. N'y a-t-il pas de propriété qui ne les ajoute pas mais ne les définit réellement que pour le fichier / la cible spécifié?
Baradé
2
Que pouvons-nous faire quand -fno-flag n'est pas disponible (et que -fflag est défini)?
gnzlbg
@ Baradé Vous ne pouvez pas - pas pour un fichier source.
Fraser
@gnzlbg Encore une fois, nous sommes à peu près coincés. J'ai mis à jour ma réponse pour donner un peu plus d'informations (et une solution de contournement possible qui fonctionnerait probablement dans certains scénarios).
Fraser
N'y a-t-il vraiment aucune solution de contournement au paramètre d'options de compilation de fichier unique? Je dois désactiver la génération de couverture gcc pour certains fichiers qui plantent gcov.
Lothar
5

Juste ajouter à la bonne réponse de @ Fraser.

Dans le cas où vous souhaitez ajouter l'indicateur spécial à des dossiers spécifiques, vous pouvez faire:

file(GLOB SPECIAL_SRC_FILES
        "path/one/src/*.cpp"
        "path/two/src/*.cpp")
set_property(SOURCE ${SPECIAL_SRC_FILES} PROPERTY COMPILE_FLAGS -Wno-effc++)

ou

file(GLOB SPECIAL_SRC_FILES
        "path/one/src/*.cpp"
        "path/two/src/*.cpp")
set_source_files_properties(${SPECIAL_SRC_FILES} PROPERTIES COMPILE_FLAGS -Wno-effc++)

Notez qu'il n'est pas recommandé d'utiliser GLOB comme indiqué ici

Levon
la source
0

En utilisant @Fraser answer, j'ai créé ce qui suit pour gérer les inclusions Qt car la variable comprend plusieurs chemins séparés par des points-virgules. Cela signifie que je devais d'abord ajouter une foreach()boucle et créer les indicateurs d'inclusion à la main . Mais cela me permet d'avoir une exception: foo.cpp (ce fichier utilise Qt pour l'instant mais à long terme, je veux supprimer cette dépendance et je veux m'assurer que Qt ne s'infiltre nulle part ailleurs).

find_package(Qt5Core REQUIRED)
set(QT_INCLUDE_PROPERTIES "")
foreach(DIR ${Qt5Core_INCLUDE_DIRS})
    set(QT_INCLUDE_PROPERTIES "${QT_INCLUDE_PROPERTIES} -isystem ${DIR}")
endforeach()
set_source_files_properties(foo.cpp PROPERTIES
    COMPILE_FLAGS
        ${QT_INCLUDE_PROPERTIES}
)

Notez également que j'utilise au -isystemlieu de -Ipour éviter certains avertissements générés par les en-têtes Qt (j'ai une tonne d'avertissements activés).

Alexis Wilke
la source