使用 CMake 检测支持的 C++ 标准

mcm*_*yer 6 c++ cmake

我有一个基于 cmake 的小型 C++11 库,可以通过使用一些 C++14 和一些 C++17 特性来改进。

为此,我希望 CMake 测试cxx_std_14和/或cxx_std_17是否在列表CMAKE_CXX_COMPILE_FEATURES 中,如相关的 SO 问题How to detect C++11 support of a compiler with CMake 中所暗示的那样。

不过,我不太清楚如何编写此测试。我认为应该起作用的,不起作用:

list (FIND ${CMAKE_CXX_COMPILE_FEATURES} "cxx_std_14" _index)
if (${_index} GREATER -1)
   message("YAY 14")
else()
   message("NAY 14")
endif()

# -> CMake Error .... (list):
#      list sub-command FIND requires three arguments
Run Code Online (Sandbox Code Playgroud)

(因为最小的 CMake 版本是 2.8.7 我必须使用list(FIND ...)而不是更新的、更简洁的IN_LIST)。

CMAKE_CXX_COMPILE_FEATURES 似乎是一个分号分隔的字符串,所以这个丑陋的片段有效:

if ("${CMAKE_CXX_COMPILE_FEATURES}" MATCHES "cxx_std_14")
    message("YAY 14")
else()
    message("NAY 14")
endif()
Run Code Online (Sandbox Code Playgroud)

当然,这不是正确的方法......任何帮助将不胜感激。

Cad*_*hon 0

我不知道这是一个好还是坏的方法,但我通过枚举我支持的可能的编译器来做到这一点:

set(CompilerName_tmp "${CMAKE_CXX_COMPILER_ID}")
string(TOLOWER "${CompilerName_tmp}" CompilerName_tmp)
set(CompilerVersion_tmp "${CMAKE_CXX_COMPILER_VERSION}")
if(LINUX)
    if("${CompilerName_tmp}" STREQUAL "gnu")
        set(CompilerName_tmp "gcc")
        endif()
        if("${CompilerVersion_tmp}" VERSION_LESS "4.8.1")
            set(Cxx11Available FALSE CACHE INTERNAL "")
        else()
            set(Cxx11Available TRUE CACHE INTERNAL "")
        endif()
    else()
        message(FATAL_ERROR "Unexpected compiler: ${CMAKE_CXX_COMPILER}")
    endif()
elseif(WINDOWS)
    if("${CompilerName_tmp}" STREQUAL "intel")
        if("${CompilerVersion_tmp}" VERSION_LESS "15.0.0")
            set(Cxx11Available FALSE CACHE INTERNAL "")
        else()
            set(Cxx11Available TRUE CACHE INTERNAL "")
        endif()
    else()
        message(FATAL_ERROR "Unexpected compiler: ${CMAKE_CXX_COMPILER}")
    endif()
endif()
Run Code Online (Sandbox Code Playgroud)

另一种可能性是将您使用的所有 C++11 功能放在一个示例中,并尝试try_compile在配置期间对其进行编译。