86 votes

Comment détecter le support c ++ 11 d'un compilateur avec cmake

Est-il un moyen pour que cmake détecter automatiquement si un compilateur prend en charge le C++11 ou pas?

Comme il serait bon d'informer les utilisateurs lors de l'cmake exécuter que le code ne compilera pas que le compilateur n'a pas de support de C++11. Au moment où j'ai mis le C++11 drapeaux toutefois, si un compilateur ne supporte pas l'utilisateur d'avoir des erreurs de compilation au lieu d'une erreur au cours de la cmake exécuter.

Parfait serait quelque chose qui travail comme find_package() cependant, je n'ai pas trouvé de module de la fonction, qui fournit les fonctionnalités nécessaires.

De plus il serait bien d'avoir la fonctionnalité pour détecter si le compilateur a besoin de l'drapeaux std=c++0x ou std=c++11.

Est-il quelque chose de disponible ou n'ai-je besoin de développer cela sur mon propre?

Voici quelque code que j'utilise jusqu'à présent, toutefois, il ne fonctionne qu'avec GNU gcc compilateurs. Ce serait bien si il y aurait plus de solution générale.

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)

109voto

Erik Sjölund Points 1841

Si vous commencez à l'aide d'une nightly build de l'actuel CMake de la direction du développement, vous pouvez tester pour le C++11 caractéristiques comme ceci

cmake_minimum_required(VERSION 3.0.20140410 FATAL_ERROR)
project(foobar CXX)
message("Out of all possible C++ compiler features CMake knows about:")
foreach(i ${CMAKE_CXX_KNOWN_FEATURES})
  message("  ${i}")
endforeach()
message("")
message("your C++ compiler supports these features"
foreach(i ${CMAKE_CXX_COMPILE_FEATURES})
  message("  ${i}")
endforeach()

Mais normalement, vous n'avez pas besoin d'utiliser ces variables CMake. Au lieu de cela, vous indiquez ce que le C++ caractéristiques sont requises dans chaque CMake cible.

Par exemple, ce programme en C++ avec le nom de fichier main.cc fait usage de certaines de C++11) caractéristiques:

#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;
}

Cette CMakeLists.txt le fichier de construire

cmake_minimum_required(VERSION 3.0.20140410 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})

Dans le fichier partager/cmake-3.0/Aide/variable/CMAKE_CXX_KNOWN_FEATURES.tvd dans le CMake package, vous pouvez trouver plus de documentation sur la Des fonctionnalités C++ CMake connaît.

Remarque, cette fonctionnalité n'a pas encore été publiés dans une écurie de CMake la sortie, donc je suppose que, seulement utiliser cette option si vous voulez expérimenter.

Merci, pour le commentaire de Marc Glisse. Il m'a aidé à écrire cette réponse. Une vieille édition de cette réponse mentionné le CMake module FindCXXFeatures, mais que le module a été supprimée.

41voto

Matthias Vallentin Points 4165

À ce stade, CMake n'ont pas une forme commode pour support de C++11. Idéalement, vous spécifiez un C++11 projet comme ceci:

project(foo CXX11)

au début de votre CMakeLists.txt. Mais l' CXX11 type de projet n'existe pas (encore). Jusqu'alors, vous pouvez utiliser un deux-mise en scène technique:

  1. Déterminer le type et la version du compilateur
  2. Ajuster construire des drapeaux en conséquence.

Par exemple, c'est ce que j'utilise à l'appui de C++11 avec Clang et 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 ()

9voto

Mark Points 663

J'ai trouvé ce script CMake qui prétend faire exactement ce dont vous avez besoin. Il peut également vérifier les fonctionnalités individuelles de C ++ 11. Je ne pense pas qu'il puisse décider entre std=C++0x et std=C++11 .

9voto

Matt McCormick Points 126

Au moment d'écrire ces lignes (pré-GCC 4.8), il peut ne pas être une bonne idée pour détecter C++11 drapeaux et les ajouter. C'est parce que la modification de la norme (au moins pour GCC) les sauts de ABI de compatibilité, ce qui peut entraîner des erreurs de lien.

Par conséquent, l'utilisation du C++11 norme devrait explicitement spécifié avec le compilateur paramètre au cours de l' initiale de CMake configuration du projet, par exemple

CXX='g++ -std=c++11' cmake /path/to/source

Qui est, l'utilisation de-std=c++11 doit être considérée comme distincte du compilateur, qui ne doit pas être mélangé ou modifié dans un projet.

8voto

nkout Points 116
 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()
 

de http://www.guyrutenberg.com/2014/01/05/enabling-c11-c0x-in-cmake/ avec des modifications mineures

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