How to get CMake to pass either std=c++14/c++1y or c++17/c++1z based on GCC version?


C++ Problem Overview

GCC 4.x doesn't accept the --std=c++14 switch for C++14 code - it takes --std=c++1y instead. Later versions take --std=c++1z but (probably) not --std=c++17 which has not been set yet (writing this in 2016). Perhaps there are similar issues with C++11.

Does CMake have some facility (perhaps as a module) to pass the correct switch according to the GCC version?

C++ Solutions

Solution 1 - C++

When wanting to specify a particular C++ version, the recommended way to do this with CMake 3.1 and later is to use the CXX_STANDARD, CXX_STANDARD_REQUIRED and CXX_EXTENSIONS target properties, or their variable equivalents to specify target defaults. Full details can be found here, but the short version goes something like this:

cmake_minimum_required(VERSION 3.1)

# ... Define targets, etc. as usual

CMake should then select the appropriate compiler flag for the requested C++ standard based on what the compiler supports, or error out if it doesn't support the requested standard.

It should also be noted that CMake may upgrade the target to use a later language standard than the one specified by its CXX_STANDARD target property. The use of compile feature requirements (as mentioned in @FlorianWolters answer) can raise the language standard requirement. In fact, CMake will always pick the stronger language requirement specified by either the CXX_STANDARD target property or the compile feature requirements set on the target. Note also that earlier versions of the CMake documentation did not accurately reflect the way CXX_EXTENSIONS interacts with compile features. With CMake 3.21 or earlier, CXX_EXTENSIONS would only take effect if CXX_STANDARD was also specified, for most common compilers (since they are specified together with the one compiler flag). From CMake 3.22 onward, CXX_EXTENSIONS is honoured whether CXX_STANDARD is set or not.

Solution 2 - C++

Modern CMake code should use the target_compile_features command to request a specific C++ standard. This can be specified as build requirement only (PRIVATE), usage requirement only (INTERFACE) or build and usage requirement (PUBLIC).


cmake_minimum_required(VERSION 3.9.4)

add_executable(cpp-snippets "main.cpp")
target_compile_features(cpp-snippets PRIVATE cxx_std_17)

Refer to the section Requiring Language Standards in the official CMake documentation for cmake-compile-features to learn more.

Solution 3 - C++

Check if the compiler supports the flags? Perhaps something like


# Check for standard to use
check_cxx_compiler_flag(-std=c++17 HAVE_FLAG_STD_CXX17)
    # Have -std=c++17, use it
    check_cxx_compiler_flag(-std=c++1z HAVE_FLAG_STD_CXX1Z)
        # Have -std=c++1z, use it
        # And so on and on...


All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestioneinpoklumView Question on Stackoverflow
Solution 1 - C++Craig ScottView Answer on Stackoverflow
Solution 2 - C++Florian WoltersView Answer on Stackoverflow
Solution 3 - C++Some programmer dudeView Answer on Stackoverflow