Comment définir le niveau d'avertissement dans CMake?

116

Comment définir le niveau d'avertissement pour un projet (pas pour toute la solution) à l'aide de CMake ? Devrait fonctionner sur Visual Studio et GCC .

J'ai trouvé diverses options mais la plupart semblent ne pas fonctionner ou ne sont pas cohérentes avec la documentation.

Wernight
la source

Réponses:

96

MISE À JOUR: Cette réponse est antérieure à l'ère Modern CMake. Tout utilisateur sain d'esprit de CMake doit s'abstenir de jouer CMAKE_CXX_FLAGSdirectement avec et appeler la target_compile_optionscommande à la place. Vérifiez la réponse du mrts qui présente les meilleures pratiques recommandées.

Vous pouvez faire quelque chose de similaire à ceci:

if(MSVC)
  # Force to always compile with W4
  if(CMAKE_CXX_FLAGS MATCHES "/W[0-4]")
    string(REGEX REPLACE "/W[0-4]" "/W4" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
  else()
    set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /W4")
  endif()
elseif(CMAKE_COMPILER_IS_GNUCC OR CMAKE_COMPILER_IS_GNUCXX)
  # Update if necessary
  set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wno-long-long -pedantic")
endif()
mloskot
la source
Notez que les nouvelles versions de Visual Studio (au moins 2013) prennent en charge l' /Wallindicateur (qui est nommé EnableAllWarnings). Il produit encore plus d'avertissements que /W4. Cependant, d'après mon expérience, cela produit beaucoup trop d'avertissements.
Adam Badura
12
/Wallest utilisable si vous souhaitez suivre une stratégie «soustractive» pour les avertissements, tout comme celle de clang -Weverything. Au lieu de sélectionner les avertissements à activer, vous activez tout, puis sélectionnez des avertissements spécifiques à désactiver.
bames53
86

Dans CMake moderne, ce qui suit fonctionne bien:

if(MSVC)
  target_compile_options(${TARGET_NAME} PRIVATE /W4 /WX)
else()
  target_compile_options(${TARGET_NAME} PRIVATE -Wall -Wextra -pedantic -Werror)
endif()

Mon collègue a suggéré une version alternative:

target_compile_options(${TARGET_NAME} PRIVATE
  $<$<CXX_COMPILER_ID:MSVC>:/W4 /WX>
  $<$<NOT:$<CXX_COMPILER_ID:MSVC>>:-Wall -Wextra -pedantic -Werror>
)

Remplacez-le ${TARGET_NAME}par le nom réel de la cible. -Werrorest facultatif, il transforme tous les avertissements en erreurs.

Ou utilisez add_compile_options(...)si vous souhaitez l'appliquer à toutes les cibles comme suggéré par @aldo dans les commentaires.

Assurez-vous également de comprendre la différence entre PRIVATEet PUBLIC(les options publiques seront héritées par les cibles qui dépendent de la cible donnée).

mrts
la source
19
Ou simplement add_compile_options(...)si vous souhaitez l'appliquer à toutes les cibles.
aldo
1
Pour info, CMake moderne ne nécessite pas de répéter la condition dans else()ou endif().
Timmmm
1
@Timmmm Merci pour la mise en garde! Est-ce juste une note ou préférez-vous que je supprime les conditions?
mrts
1
@helmesjo Non, Timmmm faisait référence au code CMake tel qu'il existait avant la modification du 9 avril. Vous pouvez consulter l'historique des modifications pour voir les bits qui ont été supprimés, qui sont les mêmes choses que Timmmm soulignait.
FeRD
2
@aldo le problème avec add_compile_options()est que les avertissements se propageront aux cibles ajoutées via add_subdirectory(). Si vous incluez des bibliothèques externes de cette façon, vous pouvez recevoir de nombreux avertissements si cette bibliothèque a été conçue avec un niveau d'avertissement différent.
trozen
24

Certains modules CMake que j'ai écrits incluent la suppression expérimentale des avertissements cross-platfrom :

sugar_generate_warning_flags(
    target_compile_options
    target_properties
    ENABLE conversion
    TREAT_AS_ERRORS ALL
)

set_target_properties(
    foo
    PROPERTIES
    ${target_properties}
    COMPILE_OPTIONS
    "${target_compile_options}"
)

Résultat pour Xcode:

  • Définir l' CLANG_WARN_SUSPICIOUS_IMPLICIT_CONVERSIONattribut Xcode (aka paramètres de construction -> avertissements -> conversions implicites suspectes -> OUI )
  • Ajouter un indicateur de compilateur: -Werror

Makefile gcc et clang:

  • Ajouter drapeaux compilateur: -Wconversion,-Werror

Visual Studio:

  • Ajouter drapeaux compilateur: /WX,/w14244

Liens

xaxxon
la source
1
c'est dommage que cmake ne fournisse pas cette fonctionnalité
Slava
3
Bonnes nouvelles. Désolé de le poster ici et pas dans la liste de diffusion cmake, mais sans niveau ce sera inutile, il y a juste trop d'avertissements pour tous les lister explicitement. Si vous voulez l'unifier, une façon de le faire est deux cmake_level séparés - un ensemble unifié d'avertissements, basé par exemple sur clang, et native_level avec la signification spécifique pour un compilateur. L'un d'eux peut être probablement raccourci au niveau. Désolé si je n'ai pas vraiment suivi la conversation et que je me suis trompé
Slava
1
@ void.pointer soulève un point valide. Votre proposition de réponse se lit comme suit: " Je prévois d'ajouter cette fonctionnalité" . Cela ne dit pas que vous avez fait des recherches superficielles et que vous espérez maintenant que quelqu'un d'autre fasse le gros du travail pour vous. Si vous ne voulez pas être attribué à la mise en œuvre (et aux questions sur son avancement), vous devez modifier votre réponse et vous dissocier de la tâche sur laquelle vous n'avez pas progressé depuis plus d'un an.
IInspectable
"Plus d'un an plus tard, toujours pas de progrès." - Maintenant que est un point valide. Plus d'un an s'est écoulé, sans progrès. C'est une indication très forte d'un projet abandonné. Si vous voulez nous prouver le contraire, montrez-nous quelques progrès. Cela ne s'est pas produit, mais votre proposition de réponse suggère toujours que la fonctionnalité est sur le point d'être ajoutée à CMake. Pourquoi faire toute cette histoire avec une fonctionnalité qui ne sera pas disponible dans les années? Ce n'est pas du tout utile. Soit montrer des progrès, soit modifier votre réponse pour qu'elle soit moins trompeuse.
IInspectable
5
Vous ne semblez pas comprendre. Si vous suggérez que vous allez implémenter une fonctionnalité, vous devez implémenter cette fonctionnalité en temps voulu. À défaut, il vous est demandé de supprimer cette promesse de votre proposition de réponse. Vous n'avez montré aucun engagement à mettre en œuvre cette fonctionnalité, alors ne prétendez pas le contraire. Je comprends que c'est gros. Je comprends également que vous ne pourrez peut-être pas y parvenir. Je vous demande simplement de faire en sorte que votre réponse reflète cela.
IInspectable
6

Voici la meilleure solution que j'ai trouvée jusqu'à présent (y compris une vérification du compilateur):

if(CMAKE_BUILD_TOOL MATCHES "(msdev|devenv|nmake)")
    add_definitions(/W2)
endif()

Cela définira le niveau d'avertissement 2 dans Visual Studio. Je suppose qu'avec un -W2cela fonctionnerait aussi dans GCC (non testé).

Mise à jour de @Williams: ça devrait être -Wallpour GCC.

Wernight
la source
6
Le drapeau d'avertissement pour GCC serait -Wallet peut-être -Wextraaussi détaillé sur gcc.gnu.org/onlinedocs/gcc/Warning-Options.html
Milliams
1
La liste que j'utilise est -W -Wall -Wextra -pedantic. -WextraL'IIRC a été remplacé -Wdans une version ultérieure de GCC, mais je laisse les deux pour des raisons de compatibilité.
Jimmio92 du
2
Ce n'est pas le but visé par add_definitions ( "il est prévu d'ajouter des définitions de préprocesseur" ). Ce n'est pas seulement une recommandation sur les meilleures pratiques. Les arguments passés à cette commande apparaîtront dans les scripts de construction générés en invoquant des outils qui ne les attendent pas (par exemple le compilateur de ressources).
IInspectable
Ce n'est pas une "vérification du compilateur", c'est une vérification de l'outil de construction.
Thomas
3

Selon la documentation de Cmake 3.17.1 :

if (MSVC)
    # warning level 4 and all warnings as errors
    add_compile_options(/W4 /WX)
else()
    # lots of warnings and all warnings as errors
    add_compile_options(-Wall -Wextra -pedantic -Werror)
endif()

GCC et Clang partagent ces drapeaux, donc cela devrait couvrir les 3.

Geai
la source
N'utilisez pas ça. À la place, utilisez target_compile_options (). Se référer au dernier document semble être "correct", mais c'est une ancienne entrée simplement pour la compatibilité descendante.
caoanan le
1
@caoanan La documentation ne mentionne rien de rétrocompatible pour cela. add_compile_optionsest à l'échelle du répertoire, alors que target_compile_optionsc'est juste pour une seule cible.
TehWan
2
if(MSVC)
    string(REGEX REPLACE "/W[1-3]" "/W4" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
endif()

Si vous utilisez target_compile_options- cmake essaiera d 'utiliser un double /W*drapeau, qui donnera un avertissement par le compilateur.

TarmoPikaro
la source
Merci pour cela. J'utilisais naïvement le add_compile_optionsseul pour obtenir des tonnes d'avertissements qui /W3sont annulés /W4. Le fait que CMake n'aborde pas cette option rudimentaire (définition du niveau d'avertissement) est incroyable.
Résurrection le