如何用cmake检测c ++ 11编译器的支持

如果编译器支持C ++ 11,有没有办法让cmake自动检测?

因为在cmake运行期间通知用户将不会编译代码,因为编译器不支持C ++ 11。 此刻,我设置了C ++ 11标志,但是如果编译器不支持它,用户在cmake运行期间将得到编译错误而不是错误。

完美会像find_package()那样工作,但是我还没有find任何提供所需function的函数模块。

另外,如果编译器需要标记std=c++0xstd=c++11那么这个function将会很好。

有没有可用的东西,还是我需要自己开发?

这里有一些代码我使用到目前为止,但它只适用于GNU gcc编译器。 如果会有更通用的解决scheme,那将会很好。

 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) 

如果您有CMake版本3.1.0或更高版本,您可以检测C ++编译器支持的C ++function

 cmake_minimum_required(VERSION 3.1.0 FATAL_ERROR) project(foobar CXX) message("Your C++ compiler supports these C++ features:") foreach(i ${CMAKE_CXX_COMPILE_FEATURES}) message("${i}") endforeach() 

但是通常你不需要在你的CMake脚本中使用CMakevariablesCMAKE_CXX_COMPILE_FEATURES 。 相反,有两种方法可以告诉CMake:在哪个C ++标准下编译你的C ++文件,或者通过明确指定C ++标准,或者指定所需的C ++特性,让CMake诱导C ++标准。 CMake将确保C ++编译器调用正确的命令行标志(例如-std = c ++ 11)。

1.明确指定C ++标准

您可以明确指定C ++标准,通过为您的CMake目标设置CMake属性CXX_STANDARDCXX_STANDARD_REQUIRED

 $ cat /tmp/src/CMakeLists.txt project(foobar CXX) cmake_minimum_required(VERSION 3.1.0 FATAL_ERROR) add_executable(prog main.cc) set_property(TARGET prog PROPERTY CXX_STANDARD 11) set_property(TARGET prog PROPERTY CXX_STANDARD_REQUIRED ON) $ cat /tmp/src/main.cc int main() { return 0; } $ mkdir /tmp/build $ cd /tmp/build $ cmake /tmp/src -- The CXX compiler identification is GNU 4.8.2 -- Check for working CXX compiler: /usr/bin/c++ -- Check for working CXX compiler: /usr/bin/c++ -- works -- Detecting CXX compiler ABI info -- Detecting CXX compiler ABI info - done -- Detecting CXX compile features -- Detecting CXX compile features - done -- Configuring done -- Generating done -- Build files have been written to: /tmp/build $ make VERBOSE=1 | grep main.cc | grep -- "-c" /usr/bin/c++ -std=gnu++11 -o CMakeFiles/prog.dir/main.cc.o -c /tmp/src/main.cc $ 

2.指定所需的C ++特性,并让CMake引发C ++标准

您可以使用CMake命令target_compile_features来指定CMake目标中使用的C ++function。 从这个列表中,CMake将会使用C ++标准。 CMake全局属性CMAKE_CXX_KNOWN_FEATURES列出了您可以select的C ++function。

 cmake_minimum_required(VERSION 3.1.0 FATAL_ERROR) message("Your CMake version supports these C++ features:") get_property(known_features GLOBAL PROPERTY CMAKE_CXX_KNOWN_FEATURES) foreach(i ${known_features}) message("${i}") endforeach() 

例如,这个名为 main.cc的 C ++程序利用了C ++ 11的特性: cxx_strong_enumscxx_constexprcxx_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; } 

这CMakeLists.txt文件将build立它

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

在这一点上,CMake没有一个方便的forms来支持C ++ 11。 理想情况下,您可以像这样指定一个C ++ 11项目:

 project(foo CXX11) 

在你的CMakeLists.txt的开头。 但CXX11项目types不存在(还)。 在此之前,您可以使用两阶段技术:

  1. 确定编译器的types和版本
  2. 相应地调整构build标志。

例如,这就是我用Clang和GCC支持C ++ 11的原因:

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

我发现这个CMake脚本声称做你需要的东西。 它也可以检查单独的C ++ 11function。 我不认为它可以在std=C++0xstd=C++11之间做出决定。

在撰写本文时(GCC 4.8之前) ,检测C ++ 11标志并添加它们可能不是一个好主意。 这是因为改变标准(至less对于GCC) 会破坏ABI兼容性 ,这可能会导致链接错误。

因此, 在项目的初始CMakeconfiguration期间,应该使用编译器设置明确指定使用C ++ 11标准,

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

也就是说,-std = c ++ 11的使用应该像一个单独的编译器一样处理,不应该在项目中混合或更改。

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

http://www.guyrutenberg.com/2014/01/05/enabling-c11-c0x-in-cmake/稍作更改;

在CMake 3.1 *中,正确的方法是对给定的目标使用CXX_STANDARD属性。 例如,给出这个使用auto简单示例(名为main.cpp ):

 #include <iostream> #include <memory> int main() { auto num = 10; std::cout << num << std::endl; return 0; } 

以下CMakeLists.txt将启用C ++ 11支持:

 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 ) 

这将添加任何必要的标志,如-std=c++11 。 请注意, CXX_STANDARD_REQUIRED属性将防止标准衰减到较早的版本。

*我没有尝试过这个CMake 3.1,但已经validation它在CMake 3.3中工作。 3.1的文档logging了这个,所以它应该工作。

我们编写了一个CMake模块来检测和启用C ++ 11的支持,你可以在这里find:
https://github.com/NitroShare/CXX11-CMake-Macros

这仍然是一个进展中的工作,但我们正在使用它的目标是Windows / Linux / Mac的许多Qt项目。 目前只支持MSVC ++,GCC和Clang。

例:

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