Wie aktiviere ich C ++ 11 in CMake?

356

Wenn ich versuche, ein von CMake generiertes Makefile auszuführen, um mein Programm zu kompilieren, wird der Fehler angezeigt

Für Schleifen basierende Bereiche werden im C ++ 98-Modus nicht unterstützt.

Ich habe versucht add_definitions(-std=c++0x), meine zu ergänzen CMakeLists.txt, aber es hat nicht geholfen.

Ich habe es auch versucht:

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

Wenn ich das tue g++ --version, bekomme ich:

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

Ich habe es auch versucht SET(CMAKE_CXX_FLAGS "-std=c++0x"), was auch nicht funktioniert.

Ich verstehe nicht, wie ich C ++ 11-Funktionen mit CMake aktivieren kann.

Subhamoy S.
quelle
11
Das SET(CMAKE_CXX_FLAGS "-std=c++0x")funktioniert gut für mich, daher gibt es wahrscheinlich irgendwo anders ein Problem in der CMakeLists-Datei. Stellen Sie sicher, dass Sie den Inhalt von CMAKE_CXX_FLAGS später nicht versehentlich überschreiben.
ComicSansMS
7
add_definitions (-std = c ++ 11) funktioniert für mich mit CMake 2.8.8
kyku
@ComicSansMS: Sie haben völlig Recht! Ich habe es überschrieben, was mein eigener Fehler war. Ich habe es korrigiert und jetzt funktioniert es gut! C ++ 11 Zeug ist sehr cool! Ich wollte einen Vektor von Strukturen schleifen, der Iterator und unnötiges Codierungsrauschen erfordern würde, wenn ich keinen Bereich für Schleifen hätte. Ich denke, ich könnte BOOST_FOREACH verwenden, aber
na ja
32
Für CMake ≥3.1 set(CMAKE_CXX_STANDARD 11)(vor dem Definieren des Ziels) ist der beste Weg.
Emlai
@tuple_cat Sie können dies auch zielbasiert tun. Beachten Sie jedoch, dass CXX_STANDARDdies unter MSVC nicht funktioniert. Sie müssen also grundsätzlich darauf zurückgreifen, target_compile_featureswenn Sie etwas möchten, das plattformübergreifend funktioniert.
Ela782

Antworten:

395

CMake 3.1 hat die Variable CMAKE_CXX_STANDARD eingeführt, die Sie verwenden können. Wenn Sie wissen, dass CMake 3.1 immer verfügbar ist, können Sie dies einfach in Ihre CMakeLists.txt-Datei der obersten Ebene schreiben oder direkt vor dem Definieren eines neuen Ziels einfügen:

set (CMAKE_CXX_STANDARD 11)

Wenn Sie ältere Versionen von CMake unterstützen müssen, finden Sie hier ein Makro, das Sie verwenden können:

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)

Das Makro unterstützt derzeit nur GCC, es sollte jedoch unkompliziert sein, es auf andere Compiler auszudehnen.

Dann können Sie use_cxx11()oben in jede CMakeLists.txt-Datei schreiben , die ein Ziel definiert, das C ++ 11 verwendet.

CMake-Problem Nr. 15943 für Clang-Benutzer, die auf macOS abzielen

Wenn Sie CMake verwenden und auf macOS klicken, gibt es einen Fehler , der dazu führen kann, dass die CMAKE_CXX_STANDARDFunktion einfach nicht funktioniert (keine Compiler-Flags hinzufügen). Stellen Sie sicher, dass Sie eines der folgenden Dinge tun:

  • Verwenden Sie cmake_minimum_required , um CMake 3.0 oder höher zu benötigen, oder
  • Setzen Sie die Richtlinie CMP0025 mit dem folgenden Code oben in Ihrer CMakeLists.txt-Datei vor dem projectBefehl auf NEW.

    # Fix behavior of CMAKE_CXX_STANDARD when targeting macOS.
    if (POLICY CMP0025)
      cmake_policy(SET CMP0025 NEW)
    endif ()
David Grayson
quelle
12
Dies sollte die akzeptierte Antwort sein. Es ist nicht erforderlich, die Eigenschaften jedes Ziels einzeln zu berühren, und es funktioniert plattformübergreifend.
DevSolar
4
Einverstanden sollte dies die akzeptierte Antwort ab CMake 3.1+ sein. Auf dem Mac scheint es für mich allerdings nicht zu funktionieren. Sie können erzwingen, dass Sie --std = c ++ 11 mit --stdlib = libc ++ erhalten, der Standardeinstellung auf dem Mac. Stattdessen enthält CMAKE_CXX_STANDARD immer die gnu-Erweiterungen, wenn sie unterstützt werden, und das Ergebnis scheint nicht gegen --stdlib = libc ++ zu bauen. Stattdessen müssen Sie zu gnus --stdlib = libstdc ++ wechseln. Der Mac ist jedoch der Sonderfall. Unter Linux ist die Auswahl von gnu ++ 11 mit libstdc ++ die Norm. Dies lässt sich natürlich leicht mit einem if (APPLE) add_compile_options () korrigieren, um die Flags anzuheften.
Atifm
2
Ein Problem dieses Ansatzes besteht darin, dass gnu++11erzwungen wird, selbst wenn diese Variablen definiert sind set(CMAKE_ANDROID_NDK_TOOLCHAIN_VERSION clang) set(CMAKE_ANDROID_STL_TYPE c++_static). Für mich war der einzige Weg der Klassikerset (CMAKE_CXX_FLAGS "-std=c++11 ${CMAKE_CXX_FLAGS}")
Antonio
2
Funktioniert nicht für mich unter macOS (CMake 3.9.4, Homebrew-Clang). Anderen die Verzweiflung retten. Ich bin mir nicht sicher, warum es für @EvanMoran funktioniert, aber nicht für mich.
Unapiedra
2
@ Unapiedra: Es ist ein CMake-Fehler, aber Sie können ihn umgehen
David Grayson
186

Mit dem Befehl CMake target_compile_features()wird die erforderliche C ++ - Funktion angegeben cxx_range_for. CMake veranlasst dann die Verwendung des C ++ - Standards.

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)

add_definitions(-std=c++11)Die CMake-Variable CMAKE_CXX_FLAGSmuss nicht verwendet oder geändert werden , da CMake sicherstellt, dass der C ++ - Compiler mit den entsprechenden Befehlszeilenflags aufgerufen wird.

Möglicherweise verwendet Ihr C ++ - Programm andere C ++ - Funktionen als cxx_range_for. Die globale CMake-Eigenschaft CMAKE_CXX_KNOWN_FEATURESlistet die C ++ - Funktionen auf, aus denen Sie auswählen können.

Anstatt zu verwenden target_compile_features(), können Sie den C ++ - Standard auch explizit angeben, indem Sie die CMake-Eigenschaften CXX_STANDARD und CXX_STANDARD_REQUIREDIhr CMake-Ziel festlegen .

Siehe auch meine ausführlichere Antwort .

Erik Sjölund
quelle
4
Es scheint, dass die Bearbeitung von heute irreführend ist. CMake 3.0.0 enthält keine target_compile_features. Korrigiere mich, wenn ich falsch liege. Ich denke, der Befehl ist nur in den nächtlichen Builds von CMake vorhanden.
Erik Sjölund
4
Ich würde sagen, dies ist die genaueste Antwort
Michał Walenciak
8
Ich denke, so soll es sein. Die anderen Antworten fügen nur manuell Flags hinzu und führen daher zu Inkompatibilitäten. Dies scheint jedoch nur in CMake 3.1+
Uli Köhler
2
@ UliKöhler dies ist eigentlich noch nicht verfügbar und kann möglicherweise für einige Compiler in 3.2 auftauchen . Verwenden Sie diese Methode nicht kurzfristig. Es ist völlig nicht tragbar.
Doug
2
Irgendeine Idee, wie man das in CMake 2.6 macht?
Nuzzolilo
93

ich benutze

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()

Aber wenn du damit spielen willst C++11, g++ 4.6.1ist das ziemlich alt. Versuchen Sie, eine neuere g++Version zu erhalten.

KoKuToru
quelle
4
Dies ist für mich die einzig richtige und nette Antwort auf diese Frage, mit dem aktuellen (ausgerollten) cmake unter den neuesten Linux-Versionen mit g ++.
Patrick B.
1
Kopiert und eingefügt und es hat perfekt funktioniert. Ich bin mit CMAKE 2.8.9 auf Cygwin. Ich kenne die meisten Ansätze, die ich hier lese, weil ich der CMAKE-Mailingliste folge und WebKit auf eine Vielzahl von Compilern portiert habe. Für WebKit-Ports hatten wir CMake 2.8.12 installiert. Da ich jedoch weiß, dass Cygwins CMAKE alt ist, wollte ich etwas, das auf diese Version zutrifft. (WebKit nicht nach Cygwin portieren, sorry)
Cardiff Space Man
Großartig, dies ist ein Drop-In für altes CMake und g ++ 4.6 (und zukunftssicher). Ich habe auch die CXX_STANDARDAntworten auf der Basis positiv bewertet , aber dies war die einzige Antwort, die in meiner Situation nützlich war.
Tomasz Gandor
Dies ist genau das, wonach ich gesucht habe, es ist jedoch nicht klar, welche cmake-Mindestversion für die Verwendung dieses Moduls erforderlich ist. cmake --help-module hilft nicht viel dabei.
Jan Segre
1
@ JanSegre das Modul erschien zuerst in 2.4, cmake.org/…
KoKuToru
57

Der einfachste Weg, den Cxx-Standard festzulegen, ist:

 set_property(TARGET tgt PROPERTY CXX_STANDARD 11)

Weitere Informationen finden Sie in der CMake-Dokumentation .

Luckyrand
quelle
2
Ja, dies scheint definitiv eine der besten Möglichkeiten zu sein, dies in modernem CMake (3.1+) zu tun
Erbureth sagt Reinstate Monica
14
Oder Sie können einfach set(CMAKE_CXX_STANDARD 11)die Standardeigenschaft für alle danach erstellten Ziele definieren.
Emlai
1
Dies ist auch die Lösung, die Sie benötigen, wenn Sie unterschiedliche C ++ - Standards für unterschiedliche Ziele festlegen möchten, da der setvon @emlai vorgeschlagene Befehl global ist und alle nachfolgenden Ziele betrifft.
Elliott Slaughter
40

Wie sich herausstellt, werden SET(CMAKE_CXX_FLAGS "-std=c++0x")viele C ++ 11-Funktionen aktiviert. Der Grund, warum es nicht funktionierte, war, dass die Aussage so aussah:

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

Nach diesem Ansatz wurde die -std=c++0xFlagge irgendwie überschrieben und es funktionierte nicht. Das Setzen der Flags nacheinander oder die Verwendung einer Listenmethode funktioniert.

list( APPEND CMAKE_CXX_FLAGS "-std=c++0x ${CMAKE_CXX_FLAGS} -g -ftest-coverage -fprofile-arcs")
Subhamoy S.
quelle
36
Ich benutze immer nur: SET (CMAKE_CXX_FLAGS "$ {CMAKE_CXX_FLAGS} -std = c ++ 11") # für gcc> = 4.7 oder c ++ 0x für 4.6
David Doria
Ich habe einmal ein kleines Skript dafür gemacht (allerdings nicht vollständig): github.com/Morwenn/POLDER/blob/master/cmake/set_cxx_norm.cmake
Morwenn
9
-1. Wenn Sie in der Befehlszeile CMAKE_CXX_FLAGS angeben, erzeugt die zweite Methode ein Semikolon im Build-Befehl (und wiederholt das ursprüngliche CMAKE_CXX_FLAGS zweimal).
Nikolai
Anstatt das Flag -g manuell hinzuzufügen, sollten Sie die Variable CMAKE_BUILD_TYPE auf debug setzen: Voices.canonical.com/jussi.pakkanen/2013/03/26/…
bames53
1
Die CXX_STANDARDEigenschaft ist besser, da sie compilerunabhängig ist.
Jaskmar
23

Der einfachste Weg:

add_compile_options(-std=c++11)

Alvarez
quelle
5
Nur verfügbar ab cmake 3.0
Raúl Salinas-Monteagudo
4
Dies führt zu Warnungen und Fehlern beim Kompilieren von C-Dateien im selben Projekt.
Rosenwasser
19

Für CMake 3.8 und höher können Sie verwenden

target_compile_features(target PUBLIC cxx_std_11)
Wimper
quelle
1
Dies ist der Weg empfohlen von der neuesten Version von CMake
Camino
Was ist die Funktion von PUBLIChier?
Rotsiser Mho
2
@RotsiserMho PUBLICbedeutet, dass andere Ziele, die von Ihrem Ziel abhängen, ebenfalls C ++ 11 verwenden. Wenn Ihr Ziel beispielsweise eine Bibliothek ist, werden alle Ziele, die mit Ihrer Bibliothek verknüpft target_link_librariessind, mit C ++ 11-Unterstützung kompiliert.
Wimpern
17

Dies ist eine weitere Möglichkeit, die C ++ 11-Unterstützung zu aktivieren.

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

Ich habe Fälle festgestellt, in denen nur diese Methode funktioniert und andere Methoden fehlschlagen. Vielleicht hat es etwas mit der neuesten Version von CMake zu tun.

Hindol
quelle
9
Dies funktioniert nur, wenn Sie NUR den C ++ - Compiler verwenden. Wenn Sie auch den CC-Compiler verwenden, schlägt dies fehl.
Emmanuel
5
add_definitionswird nur zum Hinzufügen von DEFINITIONEN verwendet, dh -D ETWAS. Und wie @Emmanuel sagte, funktioniert es in vielen Fällen nicht.
Xuhdev
Ich habe das vorher benutzt, hatte aber Probleme, als ich eine C-Datei einfügte, weil sie add_definitionsnicht zum Setzen von Flags gemacht wurde.
Jan Segre
17

Bei modernen CMake (> = 3.1) ist der beste Weg, globale Anforderungen zu setzen ,:

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

Es bedeutet "Ich möchte C ++ 11 für alle Ziele, es ist nicht optional, ich möchte keine GNU- oder Microsoft-Erweiterungen verwenden." Ab C ++ 17 ist dies meiner Meinung nach immer noch der beste Weg.

Quelle: Aktivieren von C ++ 11 und höher in CMake

MateuszL
quelle
1
Dieser Weg ist nicht ideal für die neuesten Versionen von C ++, wenn Sie nicht über das neueste CMake verfügen. Beispielsweise können Sie C ++ 2a auf diese Weise erst mit CMake 3.12 aktivieren.
Ruslan
6

Für mich funktioniert es, die folgende Zeile in Ihrer CMakeLists.txt festzulegen:

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

Durch Festlegen dieses Befehls werden die C ++ 11-Funktionen für den Compiler aktiviert. Nach Ausführung des cmake ..Befehls sollten Sie in der Lage sein, range based for loopsIhren Code zu verwenden und fehlerfrei zu kompilieren.

Kevin Katzke
quelle
Dies ist am Ende die beste Antwort, wenn Sie genau wollen -std=c++11, da set (CMAKE_CXX_STANDARD 11)die Flagge verwendet wird -std=gnu++11, was möglicherweise unerwünscht ist.
Antonio
1
@ Antonioset (CMAKE_CXX_EXTENSIONS OFF)
Mloskot
3

Ich denke nur diese beiden Zeilen sind genug.

set(CMAKE_CXX_STANDARD 11)

set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
Ehsan Panahi
quelle
1
Dies ist sinnvoll, wenn alle Ziele in einem Projekt denselben C ++ - Standard verwenden (alle kompilierten Bibliotheken und ausführbaren Dateien verwenden beispielsweise C ++ 11). Andernfalls ist die Cmake- target_compile_featuresFunktion, die für jedes einzelne Ziel angewendet wird, wie in anderen Antworten gezeigt, ein empfehlenswerterer Ansatz.
Allan
3

Für den Fall, dass Sie immer den neuesten C ++ - Standard aktivieren möchten, ist hier meine Erweiterung der Antwort von David Grayson angesichts der jüngsten (CMake 3.8 und CMake 3.11) Ergänzungen der Werte 17 und 20 für 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()
    SET(CMAKE_CXX_STANDARD 20)
ENDIF()

# Typically, you'll also want to turn off compiler-specific extensions:
SET(CMAKE_CXX_EXTENSIONS OFF)

(Verwenden Sie diesen Code anstelle set (CMAKE_CXX_STANDARD 11)der verknüpften Antwort.)

Kodierung
quelle
1

Modernes cmake bietet einfachere Möglichkeiten, Compiler für die Verwendung einer bestimmten Version von C ++ zu konfigurieren. Das einzige, was jemand tun muss, ist die relevanten Zieleigenschaften festzulegen. Unter den von cmake unterstützten Eigenschaften werden die folgenden verwendet, um zu bestimmen, wie Compiler für die Unterstützung einer bestimmten Version von C ++ konfiguriert werden:

  • CXX_STANDARDLegt den C ++ - Standard fest, dessen Funktionen zum Erstellen des Ziels angefordert werden. Stellen Sie dies als 11Ziel für C ++ 11 ein.

  • CXX_EXTENSIONS, ein Boolescher Wert, der angibt, ob compilerspezifische Erweiterungen angefordert werden. Wenn Sie dies als Offdeaktivieren, wird die Unterstützung für alle compilerspezifischen Erweiterungen deaktiviert.

Um dies zu demonstrieren, ist hier ein minimales Arbeitsbeispiel für a CMakeLists.txt.

cmake_minimum_required(VERSION 3.1)

project(testproject LANGUAGES CXX )

set(testproject_SOURCES
    main.c++
    )

add_executable(testproject ${testproject_SOURCES})

set_target_properties(testproject
    PROPERTIES
    CXX_STANDARD 11
    CXX_EXTENSIONS off
    )
RAM
quelle
-5

OS X und Homebrew LLVM im Zusammenhang:

Vergessen Sie nicht, danach cmake_minimum_required (VERSION 3.3) und project () aufzurufen!

Oder CMake wird project()implizit vor Zeile 1 eingefügt , was zu Problemen bei der Erkennung der Clang-Version und möglicherweise zu anderen Problemen führt. Hier ist ein verwandtes Problem .

senz
quelle
2
Die Frage bezieht sich nicht speziell auf OSX oder LVVM. Es gibt auch keinen Grund, CMake v3.x für die C ++ 11-Entwicklung zu benötigen. Was die Erkennung von Clang-Versionen betrifft, so hat OP nicht danach gefragt.
Einpoklum