如何使用CMake检测编译器的C ++ 11支持

时间:2012-06-11 16:59:41

标签: c++ c++11 cmake

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

因为在CMake运行期间通知用户,代码将无法编译会很好,因为编译器不支持C ++ 11。目前我设置了C ++ 11标志。但是,如果编译器不支持它,则用户在CMake运行期间会收到编译错误而不是错误。

完美将是像find_package()一样的东西。但是,我没有找到任何提供所需功能的模块或功能。

另外,使用该功能检测编译器是否需要标记std=c++0xstd=c++11会很好。

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

下面是我目前使用的一些代码,但它只适用于GNU'c GCC编译器。如果能有更通用的解决方案,那就太好了。

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)

7 个答案:

答案 0 :(得分:93)

如果您使用的是CMake 3.1.0或更高版本,则可以检测到C ++的功能 你的C ++编译器支持

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脚本中使用CMake变量 CMAKE_CXX_COMPILE_FEATURES 。相反,有两种方法可以告诉CMake C ++标准应该编译C ++文件 明确指定C ++标准或通过指定所需的C ++特性并让CMake引入C ++标准。 CMake将确保使用正确的命令行标志调用C ++编译器(例如-std = c ++ 11)。

1。明确指定C ++标准

您可以通过设置CMake属性明确指定C ++标准 CXX_STANDARD  和 {CM}目标的CXX_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 ++功能。从这个列表中,CMake将导致使用C ++标准。 CMake全局属性CMAKE_CXX_KNOWN_FEATURES列出了您可以选择的C ++功能。

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

此CMakeLists.txt文件将构建它

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

答案 1 :(得分:43)

此时,CMake没有方便的表单来支持C ++ 11。理想情况下,您可以指定一个C ++ 11项目:

project(foo CXX11)

CMakeLists.txt的开头。但是CXX11项目类型不存在(尚未)。在此之前,您可以使用两阶段技术:

  1. 确定编译器类型和版本
  2. 相应地调整构建标记。
  3. 例如,这是我用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 ()
    

答案 2 :(得分:10)

我发现this CMake script声称可以完全满足您的需求。它还可以检查各个C ++ 11的功能。我不认为它可以在std=C++0xstd=C++11之间做出决定。

答案 3 :(得分:9)

在撰写本文(pre-GCC 4.8)时,检测C ++ 11标志并添加它们可能不是一个好主意。这是因为更改标准(至少对于GCC)breaks ABI compatibility,这可能导致链接错误。

因此,在initial CMake configuration of the project期间应使用编译器设置明确指定C ++ 11标准的使用,例如

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

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

答案 4 :(得分:8)

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/

稍作修改

答案 5 :(得分:4)

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

#include <iostream>

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_CXX_KNOWN_FEATURES的正确且非简单的方式,例如cxx_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)

*我没有在CMake 3.1上尝试这个,但已经验证它在CMake 3.3中有效。 documentation for 3.1会对此进行记录,以便它可以正常工作。

答案 6 :(得分:1)

我们编写了一个用于检测和启用C ++ 11支持的CMake模块,您可以在此处找到:
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()