web-dev-qa-db-fra.com

Comment obtenir que CMake passe std = c ++ 14 / c ++ 1y ou c ++ 17 / c ++ 1z basé sur la version de GCC?

GCC 4.x n'accepte pas le --std=c++14 commutateur pour le code C++ 14 - il faut --std=c++1y au lieu. Les versions ultérieures prennent --std=c++1z mais pas (probablement) --std=c++17 qui n'a pas encore été défini (écrit en 2016). Il existe peut-être des problèmes similaires avec C++ 11.

CMake a-t-il une possibilité (peut-être en tant que module) de passer le commutateur approprié en fonction de la version de GCC?

39
einpoklum

Lorsque vous souhaitez spécifier une version C++ particulière, la méthode recommandée avec CMake 3.1 et versions ultérieures consiste à utiliser le fichier CXX_STANDARD, CXX_STANDARD_REQUIRED et CXX_EXTENSIONS propriétés cibles ou leurs équivalents variables pour spécifier les valeurs par défaut de la cible. Les détails complets peuvent être trouvés ici , mais la version courte ressemble à ceci:

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 ensuite sélectionner le drapeau de compilateur approprié pour la norme C++ demandée en fonction de ce que le compilateur prend en charge, ou en cas d'erreur s'il ne prend pas en charge la norme demandée.

Il convient également de noter que CMake peut mettre à niveau la cible pour utiliser une norme de langue plus récente que celle spécifiée par son CXX_STANDARD propriété cible. L'utilisation de exigences de compilation (comme indiqué dans la réponse de @FlorianWolters) peut augmenter les exigences de la norme de langue. En fait, CMake choisira toujours l'exigence linguistique plus stricte spécifiée par le CXX_STANDARD propriété cible ou exigences de compilation définies sur la cible. Notez également que la documentation de CMake à partir de 3.10.1 ne reflète pas exactement la façon dont CXX_EXTENSIONS interagit avec les fonctionnalités de compilation, comme CXX_EXTENSIONS ne prend effet que si CXX_STANDARD est également spécifié pour les compilateurs les plus courants (car ils sont spécifiés avec le drapeau du compilateur).

68
Craig Scott

Le code CMake moderne devrait utiliser le target_compile_features commande pour demander une norme C++ spécifique. Cela peut être spécifié uniquement comme exigence de construction (PRIVATE), comme exigence d’utilisation seulement (INTERFACE) ou comme exigence 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 relative aux normes linguistiques dans la documentation officielle de CMake pour cmake-compile-features pour en savoir plus.

22
Florian Wolters

Vérifiez si le compilateur prend en charge 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()
9