web-dev-qa-db-fra.com

Comment activer C ++ 11 dans CMake?

Quand j'essaie de lancer le makefile généré par CMake pour compiler mon programme, je reçois le message d'erreur suivant:

les boucles basées sur la plage for ne sont pas prises en charge en mode C++ 98.

J'ai essayé d'ajouter add_definitions(-std=c++0x) à mon CMakeLists.txt, mais cela n'a pas aidé. J'ai aussi essayé ça:

if(CMAKE_COMPILER_IS_GNUCXX)
    add_definitions(-std=gnu++0x)
endif()

Quand je fais g++ --version, je reçois:

g ++ (Ubuntu/Linaro 4.6.1-9ubuntu3) 4.6.1

J'ai aussi essayé SET(CMAKE_CXX_FLAGS "-std=c++0x"), qui ne fonctionne pas non plus.

Je ne comprends pas comment activer les fonctionnalités de C++ 11 à l'aide de CMake.

339

Il s'avère que SET(CMAKE_CXX_FLAGS "-std=c++0x") active de nombreuses fonctionnalités C++ 11. La raison pour laquelle cela n'a pas fonctionné était que l'énoncé ressemblait à ceci:

set(CMAKE_CXX_FLAGS "-std=c++0x ${CMAKE_CXX_FLAGS} -g -ftest-coverage -fprofile-arcs")

Suivant cette approche, l’indicateur -std=c++0x a été écrasé et il n’a pas fonctionné. La définition des indicateurs un par un ou l'utilisation d'une méthode de liste fonctionne.

list( APPEND CMAKE_CXX_FLAGS "-std=c++0x ${CMAKE_CXX_FLAGS} -g -ftest-coverage -fprofile-arcs")
40

CMake 3.1 a introduit la variable CMAKE_CXX_STANDARD que vous pouvez utiliser. Si vous savez que vous aurez toujours CMake 3.1 disponible, vous pouvez simplement l'écrire dans votre fichier CMakeLists.txt de niveau supérieur ou le placer juste avant la définition de toute nouvelle cible:

set (CMAKE_CXX_STANDARD 11)

Si vous avez besoin de supporter les anciennes versions de CMake, voici une macro que j'ai créée et que vous pouvez utiliser:

macro(use_cxx11)
  if (CMAKE_VERSION VERSION_LESS "3.1")
    if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
      set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=gnu++11")
    endif ()
  else ()
    set (CMAKE_CXX_STANDARD 11)
  endif ()
endmacro(use_cxx11)

La macro ne supporte que GCC pour le moment, mais il devrait être simple de l'étendre à d'autres compilateurs.

Vous pouvez ensuite écrire use_cxx11() en haut de tout fichier CMakeLists.txt qui définit une cible utilisant C++ 11.

CMake numéro 15943 pour les utilisateurs clangs ciblant macOS

Si vous utilisez CMake et clang pour cibler macOS, il existe un bogue qui peut empêcher la fonctionnalité CMAKE_CXX_STANDARD de fonctionner (ne pas ajouter d'indicateur de compilation). Assurez-vous de faire l'une des choses suivantes:

  • Utilisez cmake_minimum_required pour exiger CMake 3.0 ou une version ultérieure, ou
  • Définissez la stratégie CMP0025 sur NEW avec le code suivant en haut de votre fichier CMakeLists.txt avant la commande project:

    # Fix behavior of CMAKE_CXX_STANDARD when targeting macOS.
    if (POLICY CMP0025)
      cmake_policy(SET CMP0025 NEW)
    endif ()
    
359
David Grayson

La commande CMake target_compile_features() est utilisée pour spécifier la fonctionnalité C++ requise cxx_range_for. CMake induira alors l’utilisation de la norme C++.

_cmake_minimum_required(VERSION 3.1.0 FATAL_ERROR)
project(foobar CXX)
add_executable(foobar main.cc)
target_compile_features(foobar PRIVATE cxx_range_for)
_

Il n’est pas nécessaire d’utiliser add_definitions(-std=c++11) ou de modifier la variable CMake CMAKE_CXX_FLAGS, car CMake s’assurera que le Le compilateur est appelé avec les indicateurs de ligne de commande appropriés.

Peut-être que votre programme C++ utilise des fonctionnalités C++ autres que _cxx_range_for_. La propriété globale CMake CMAKE_CXX_KNOWN_FEATURES répertorie les fonctionnalités C++ parmi lesquelles vous pouvez choisir.

Au lieu d'utiliser target_compile_features(), vous pouvez également spécifier explicitement la norme C++ en définissant les propriétés CMake. CXX_STANDARD et CXX_STANDARD_REQUIRED pour votre cible CMake.

Voir aussi ma réponse plus détaillée .

182
Erik Sjölund

J'utilise

include(CheckCXXCompilerFlag)
CHECK_CXX_COMPILER_FLAG("-std=c++11" COMPILER_SUPPORTS_CXX11)
CHECK_CXX_COMPILER_FLAG("-std=c++0x" COMPILER_SUPPORTS_CXX0X)
if(COMPILER_SUPPORTS_CXX11)
    set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
elseif(COMPILER_SUPPORTS_CXX0X)
    set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++0x")
else()
        message(STATUS "The compiler ${CMAKE_CXX_COMPILER} has no C++11 support. Please use a different C++ compiler.")
endif()

Mais si vous voulez jouer avec C++11, g++ 4.6.1 est assez vieux. Essayez d’obtenir une version plus récente de g++.

92
KoKuToru

Le moyen le plus simple de définir la norme Cxx est:

 set_property(TARGET tgt PROPERTY CXX_STANDARD 11)

Voir la documentation de CMake pour plus de détails.

54
Luckyrand

Le moyen le plus simple:

add_compile_options(-std=c++11)

23
alvarez

C’est une autre façon d’activer la prise en charge de C++ 11,

ADD_DEFINITIONS(
    -std=c++11 # Or -std=c++0x
    # Other flags
)

J'ai rencontré des cas où seule cette méthode fonctionne et où d'autres méthodes échouent. Peut-être que cela a quelque chose à voir avec la dernière version de CMake.

16
Hindol

Pour CMake 3.8 et plus récent, vous pouvez utiliser

target_compile_features(target PUBLIC cxx_std_11)
12
eyelash

Dans CMake moderne (> = 3.1), le meilleur moyen de définir une exigence globale est:

set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)

Cela signifie "Je veux le C++ 11 pour toutes les cibles, ce n'est pas facultatif, je ne veux utiliser aucune extension GNU ou MS". À partir de c ++ 17, c'est encore à mon humble avis le meilleur moyen.

Source: https://crascit.com/2015/03/28/enabling- cxx11-in-cmake/

9
MateuszL

Ce qui fonctionne pour moi est de définir la ligne suivante dans votre fichier CMakeLists.txt:

set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")

La définition de cette commande active les fonctionnalités C++ 11 pour le compilateur et, après l'exécution de la commande cmake .., vous devriez pouvoir utiliser range based for loops dans votre code et le compiler sans erreur.

6
Kevin Katzke

Je pense que ces deux lignes suffisent.

set(CMAKE_CXX_STANDARD 11)

set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
3
Ehsan Panahi

Si vous souhaitez activer toujours la dernière norme C++, voici mon extension de réponse de David Grayson , à la lumière des ajouts récents (CMake 3.8, CMake 3.11) des valeurs de 17 et 20 pour CMAKE_CXX_STANDARD):

IF (CMAKE_VERSION VERSION_LESS "3.8")
    SET(CMAKE_CXX_STANDARD 14)
ELSEIF (CMAKE_VERSION VERSION_LESS "3.11")
    SET(CMAKE_CXX_STANDARD 17)
ELSE() # CMake 3.11 or higher:
    SET(CMAKE_CXX_STANDARD 20)
ENDIF()
# Typically, you'll also want to turn off compiler-specific extensions:
SET(CMAKE_CXX_EXTENSIONS OFF)

(utilisez ce code à la place de set (CMAKE_CXX_STANDARD 11) dans la réponse liée).

1
codeling