68 votes

Comment faire pour que CMake passe soit std=c++14/c++1y ou c++17/c++1z en fonction de la version de GCC ?

GCC 4.x n'accepte pas l'option --std=c++14 pour le code C++14 - il faut --std=c++1y à la place. Les versions ultérieures prennent --std=c++1z mais (probablement) pas --std=c++17 qui n'a pas encore été défini (j'écris ceci en 2016). Peut-être y a-t-il des problèmes similaires avec C++11.

Est-ce que CMake a une certaine facilité (peut-être comme un module) pour passer le commutateur correct selon la version de GCC ?

1 votes

"Peut-être y a-t-il des problèmes similaires avec C++11." Ce serait c++11 contre c++0x, le premier ayant été introduit dans gcc4.7/8 environ.

1 votes

En fait, les anciens commutateurs (0x, 1y, 1z) fonctionnent très bien même sur les compilateurs qui supportent les modernes, il n'y a donc pas de réel besoin de faire ça "bien".

3 votes

Il y a est Il faut que cela soit "correct" car passer les drapeaux bruts du compilateur est un anti-modèle de CMake et va à l'encontre de tout le concept d'un système de méta-construction/générateur de système de construction.

116voto

Craig Scott Points 3981

Lorsque l'on souhaite spécifier une version particulière de C++, la manière recommandée de le faire avec CMake 3.1 et les versions ultérieures est d'utiliser la commande CXX_STANDARD , CXX_STANDARD_REQUIRED et CXX_EXTENSIONS propriétés de la cible, ou leurs équivalents variables pour spécifier les valeurs par défaut de la cible. Des détails complets peuvent être trouvés ici mais la version courte est quelque chose comme ça :

cmake_minimum_required(VERSION 3.1)
project(Example)

set(CMAKE_CXX_STANDARD 14)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)
# ... Define targets, etc. as usual

CMake devrait alors sélectionner le drapeau de compilateur approprié pour le standard C++ demandé en fonction de ce que le compilateur supporte, ou se tromper s'il ne supporte pas le standard demandé.

Il convient également de noter que CMake peut mettre à niveau la cible pour utiliser un standard de langage plus récent que celui spécifié par son fichier CXX_STANDARD la propriété de la cible. L'utilisation de compiler les exigences relatives aux fonctionnalités (comme mentionné dans la réponse de @FlorianWolters) peut augmenter l'exigence du standard de langue. En fait, CMake choisira toujours l'exigence de langage la plus forte spécifiée par l'une ou l'autre des options suivantes CXX_STANDARD ou les exigences de la fonction de compilation définies sur la cible. Notez également que la documentation de CMake, à partir de la version 3.10.1, ne reflète pas exactement la façon dont les propriétés de la cible sont définies. CXX_EXTENSIONS interagit avec les fonctions de compilation, comme CXX_EXTENSIONS ne prend effet que si CXX_STANDARD est également spécifié pour les compilateurs les plus courants (puisqu'ils sont spécifiés ensemble avec l'indicateur de compilateur unique).

41voto

Florian Wolters Points 483

Un code CMake moderne devrait utiliser l'option target_compile_features pour demander une norme C++ spécifique. Celle-ci peut être spécifiée en tant qu'exigence de construction uniquement ( PRIVATE ), l'exigence d'utilisation seulement ( INTERFACE ) ou les exigences de construction et d'utilisation ( PUBLIC ).

Exemple :

cmake_minimum_required(VERSION 3.9.4)

project(cpp-snippets)
add_executable(cpp-snippets "main.cpp")
target_compile_features(cpp-snippets PRIVATE cxx_std_17)

Reportez-vous à la section Exiger des normes linguistiques dans la documentation officielle de CMake pour cmake-compile-features pour en savoir plus.

2 votes

Que sont les "exigences de construction" par opposition aux "exigences d'utilisation" ?

6 votes

Il convient également de souligner que le soutien à la cxx_std_YY n'a été ajoutée qu'à CMake 3.8, alors que l'option CXX_STANDARD La famille des propriétés cibles existe depuis bien plus longtemps et cxx_std_YY Les méta-caractéristiques ne permettent pas à elles seules de contrôler l'utilisation ou non des extensions du compilateur.

3 votes

@einpoklum Comme utilisé dans la réponse, exigences de construction font référence aux éléments nécessaires à la construction de la cible elle-même, alors que exigences d'utilisation sont des choses que tout ce qui est lié à la cible héritera comme une exigence.

11voto

Joachim Pileborg Points 121221

Vérifier si le compilateur supporte les drapeaux ? Peut-être quelque chose comme

include(CheckCXXCompilerFlag)

# Check for standard to use
check_cxx_compiler_flag(-std=c++17 HAVE_FLAG_STD_CXX17)
if(HAVE_FLAG_STD_CXX17)
    # Have -std=c++17, use it
else()
    check_cxx_compiler_flag(-std=c++1z HAVE_FLAG_STD_CXX1Z)
    if(HAVE_FLAG_STD_CXX1Z)
        # Have -std=c++1z, use it
    else()
        # And so on and on...
    endif()
endif()

2 votes

@einpoklum Pas de spéculation, j'utilise ce code exact depuis quelques années sans problème. Avec GCC et Clang (qui, la dernière fois que j'ai essayé, ne supportait pas l'option -std=c++17 option).

1 votes

Pourquoi maintenir votre propre code, quand CMake offre tout ce que vous voulez ?

0 votes

@usr1234567 Rétrocompatibilité avec les anciennes versions de CMake qui n'ont pas les drapeaux et les paramètres pour les nouveaux standards C++.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X