Gibt es eine Möglichkeit, CMake automatisch erkennen zu lassen, ob ein Compiler C ++ 11 unterstützt oder nicht?
Es wäre schön, die Benutzer während des CMake-Laufs darüber zu informieren, dass der Code nicht kompiliert wird, da der Compiler C ++ 11 nicht unterstützt. Im Moment habe ich die C ++ 11 Flags gesetzt. Wenn ein Compiler dies jedoch nicht unterstützt, erhält der Benutzer Kompilierungsfehler anstelle eines Fehlers während des CMake-Laufs.
Perfekt wäre etwas, das funktioniert find_package()
. Ich habe jedoch kein Modul oder keine Funktion gefunden, die die erforderliche Funktionalität bietet.
Zusätzlich wäre es schön, die Funktion zu haben, um zu erkennen, ob der Compiler die Flags std=c++0x
oder benötigt std=c++11
.
Ist etwas verfügbar oder muss ich es selbst entwickeln?
Unten ist ein Code, den ich bisher verwende, der jedoch nur mit GNU'c GCC-Compilern funktioniert. Es wäre schön, wenn es eine allgemeinere Lösung gäbe.
if(CMAKE_COMPILER_IS_GNUCXX)
execute_process(COMMAND ${CMAKE_C_COMPILER} -dumpversion OUTPUT_VARIABLE GCC_VERSION)
if (GCC_VERSION VERSION_GREATER 4.7 OR GCC_VERSION VERSION_EQUAL 4.7)
message(STATUS "C++11 activated.")
add_definitions("-std=gnu++11")
elseif(GCC_VERSION VERSION_GREATER 4.3 OR GCC_VERSION VERSION_EQUAL 4.3)
message(WARNING "C++0x activated. If you get any errors update to a compiler which fully supports C++11")
add_definitions("-std=gnu++0x")
else ()
message(FATAL_ERROR "C++11 needed. Therefore a gcc compiler with a version higher than 4.3 is needed.")
endif()
else(CMAKE_COMPILER_IS_GNUCXX)
add_definitions("-std=c++0x")
endif(CMAKE_COMPILER_IS_GNUCXX)
add_definitions
Befehl anstelle der Einstellung verwendenCMAKE_CXX_FLAGS
, um die Compileroptionen festzulegen?Antworten:
Wenn Sie CMake Version 3.1.0 oder höher haben, können Sie feststellen, welche C ++ - Funktionen Ihr C ++ - Compiler unterstützt
Normalerweise müssen Sie die CMake-Variable CMAKE_CXX_COMPILE_FEATURES in Ihren CMake-Skripten nicht verwenden. Stattdessen gibt es zwei Möglichkeiten, wie Sie CMake mitteilen können, unter welchem C ++ - Standard Ihre C ++ - Dateien kompiliert werden sollen, indem Sie entweder den C ++ - Standard explizit angeben oder die erforderlichen C ++ - Funktionen angeben und CMake den C ++ - Standard einführen lassen. CMake stellt sicher, dass der C ++ - Compiler mit den richtigen Befehlszeilenflags aufgerufen wird (z. B. -std = c ++ 11).
1. Geben Sie den C ++ - Standard explizit an
Sie können den C ++ - Standard explizit angeben, indem Sie die CMake-Eigenschaften CXX_STANDARD und CXX_STANDARD_REQUIRED für Ihr CMake-Ziel festlegen .
2. Geben Sie die erforderlichen C ++ - Funktionen an und lassen Sie CMake den C ++ - Standard einführen
Mit dem CMake-Befehl target_compile_features können Sie die C ++ - Funktionen angeben, die in Ihrem CMake-Ziel verwendet werden. Aus dieser Liste veranlasst CMake die Verwendung des C ++ - Standards. Die globale CMake-Eigenschaft CMAKE_CXX_KNOWN_FEATURES listet die C ++ - Funktionen auf, aus denen Sie auswählen können.
Dieses C ++ - Programm mit dem Dateinamen main.cc verwendet beispielsweise die C ++ 11-Funktionen: cxx_strong_enums , cxx_constexpr , cxx_auto_type
#include <cstdlib> int main(int argc, char *argv[]) { enum class Color { Red, Orange, Yellow, Green, Blue, Violet }; constexpr float a = 3.1415f; auto b = a; return EXIT_SUCCESS; }
Diese CMakeLists.txt-Datei würde es erstellen
cmake_minimum_required(VERSION 3.1.0 FATAL_ERROR) project(foobar CXX) add_executable(foobar main.cc) set(needed_features cxx_strong_enums cxx_constexpr cxx_auto_type) target_compile_features(foobar PRIVATE ${needed_features})
quelle
CXX_STANDARD 11
es nicht mit demGLOBAL
Eigenschaftsbereich funktionieren , was total scheiße ist.set(CMAKE_CXX_STANDARD 11)
-std=gnu++11
nicht standardmäßige Erweiterungen hinzufügt und aktiviert. Ich möchte wirklich nurstd=c++11
eine Fehlermeldung erhalten, wenn ich versuche, eine dieser nicht standardmäßigen Erweiterungen zu verwenden, Portabilität zuerst.Derzeit verfügt CMake nicht über ein geeignetes Formular zur Unterstützung von C ++ 11. Idealerweise würden Sie ein C ++ 11-Projekt wie folgt angeben:
am Anfang Ihres
CMakeLists.txt
. DerCXX11
Projekttyp existiert aber (noch) nicht. Bis dahin können Sie eine zweistufige Technik anwenden:Zum Beispiel unterstütze ich damit C ++ 11 mit Clang und GCC:
# Initialize CXXFLAGS. set(CMAKE_CXX_FLAGS "-Wall -std=c++11") set(CMAKE_CXX_FLAGS_DEBUG "-O0 -g") set(CMAKE_CXX_FLAGS_MINSIZEREL "-Os -DNDEBUG") set(CMAKE_CXX_FLAGS_RELEASE "-O4 -DNDEBUG") set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "-O2 -g") # Compiler-specific C++11 activation. if ("${CMAKE_CXX_COMPILER_ID}" MATCHES "GNU") execute_process( COMMAND ${CMAKE_CXX_COMPILER} -dumpversion OUTPUT_VARIABLE GCC_VERSION) if (NOT (GCC_VERSION VERSION_GREATER 4.7 OR GCC_VERSION VERSION_EQUAL 4.7)) message(FATAL_ERROR "${PROJECT_NAME} requires g++ 4.7 or greater.") endif () elseif ("${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -stdlib=libc++") else () message(FATAL_ERROR "Your C++ compiler does not support C++11.") endif ()
quelle
set_property(TARGET tgt PROPERTY CXX_STANDARD 11)
.Zum Zeitpunkt dieses Schreibens (vor GCC 4.8) ist es möglicherweise keine gute Idee, C ++ 11-Flags zu erkennen und hinzuzufügen. Dies liegt daran, dass eine Änderung des Standards (zumindest für GCC) die ABI-Kompatibilität beeinträchtigt , was zu Verbindungsfehlern führen kann.
Daher sollte die Verwendung des C ++ 11-Standards bei der anfänglichen CMake-Konfiguration des Projekts explizit mit der Compilereinstellung angegeben werden , z
CXX='g++ -std=c++11' cmake /path/to/source
Das heißt, die Verwendung von -std = c ++ 11 sollte wie ein separater Compiler behandelt werden, der in einem Projekt nicht gemischt oder geändert werden darf.
quelle
Verwenden:
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(FATAL_ERROR "Compiler ${CMAKE_CXX_COMPILER} has no C++11 support.") endif()
Dies ist auf das Aktivieren von C ++ 11 (C ++ 0x) in CMake mit geringfügigen Änderungen zurückzuführen.
quelle
Wenn Sie CMake 3.8 oder höher verwenden, können Sie die Funktion verwenden
cxx_std_11
, die C ++ 11 oder höher anfordert :In CMake 3.1 * und höher besteht die richtige und einfache Möglichkeit darin, die
CXX_STANDARD
Eigenschaft für ein bestimmtes Ziel zu verwenden. Beispiel für dieses einfache Beispiel mitauto
(benanntmain.cpp
):#include <iostream> int main() { auto num = 10; std::cout << num << std::endl; return 0; }
Folgendes
CMakeLists.txt
aktiviert die C ++ 11-Unterstützung:cmake_minimum_required(VERSION 3.3) project(Hello CXX) set(SOURCE_FILES main.cpp) add_executable(Hello ${SOURCE_FILES}) set_property(TARGET Hello PROPERTY CXX_STANDARD 11 CXX_STANDARD_REQUIRED ON )
Dadurch werden alle erforderlichen Flags hinzugefügt, z
-std=c++11
. Beachten Sie, dass dieCXX_STANDARD_REQUIRED
Eigenschaft verhindert, dass der Standard auf eine frühere Version abfällt.Eine weitere geeignete , aber nicht so einfache Art und Weise die angeben ,
CMAKE_CXX_KNOWN_FEATURES
dass Sie verwenden, wie zum Beispielcxx_auto_type
:cmake_minimum_required(VERSION 3.3) project(Hello CXX) set(SOURCE_FILES main.cpp) add_executable(Hello ${SOURCE_FILES}) target_compile_features(Hello PRIVATE cxx_auto_type)
* Ich habe dies in CMake 3.1 nicht versucht, aber überprüft, dass es in CMake 3.3 funktioniert. Die Dokumentation zu 3.1 dokumentiert dies, sodass es funktionieren sollte.
quelle
Wir haben ein CMake-Modul zum Erkennen und Aktivieren der C ++ 11-Unterstützung geschrieben, das Sie hier finden:
https://github.com/NitroShare/CXX11-CMake-Macros
Es ist noch in Arbeit, aber wir verwenden es für eine Reihe von Qt-Projekten, die auf Windows / Linux / Mac abzielen. Derzeit werden nur MSVC ++, GCC und Clang unterstützt.
Beispiel:
include(CXX11) check_for_cxx11_compiler(CXX11_COMPILER) # If a C++11 compiler is available, then set the appropriate flags if(CXX11_COMPILER) enable_cxx11() endif()
quelle