Detect supported C++ standards with CMake

Viewed 294

I have a small cmake-based C++11 library that could be improved by using some C++14 and some C++17 features.

To that end I want CMake to test whether cxx_std_14 and/or cxx_std_17is in the list CMAKE_CXX_COMPILE_FEATURES, as hinted at in the related SO question How to detect C++11 support of a compiler with CMake.

I can't quite figure out how to write this test, though. What I think should work, doesn't:

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

(Because the mimumum CMake version is 2.8.7 I have to use list(FIND ...) instead of the newer, more concise IN_LIST).

CMAKE_CXX_COMPILE_FEATURES seems to be a semicolon-separated string, so this ugly snippet works:

if ("${CMAKE_CXX_COMPILE_FEATURES}" MATCHES "cxx_std_14")
    message("YAY 14")
else()
    message("NAY 14")
endif()

Surely, this isn't the proper way to do it... Any help would be appreciated.

1 Answers

I don't know if it's a good or bad way, but I do it by enumerating the possible compilers I support:

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

Another possibility is to put all the C++11 features you use in a single example, and try to compile it with try_compile during the configuration.

Related