I'm using VS 15.3, which supports integrated CMake 3.8. How can I target C++17 without writing flags for each specific compilers? My current global settings don't work:
# https://cmake.org/cmake/help/latest/prop_tgt/CXX_STANDARD.html
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)
# expected behaviour
#set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /std:c++lastest")
I expected CMake to add "/std:c++lastest" or equivalents when generating VS solution files, but no c++17 flags was found, resulted in compiler error:
C1189 #error: class template optional is only available with C++17.
From the CMake 3.9 documentation:
For compilers that have no notion of a standard level, such as MSVC, this has no effect.
In short, CMake haven't been updated to accommodate for the standard flags added to VC++ 2017.
You have to detect if VC++ 2017 (or later) is used and add the corresponding flags yourself for now.
In CMake 3.10 (and later) this have been fixed for newer version of VC++. See the 3.10 documentation.
In modern CMake, I've found it best to assign CXX standards at the target level instead of global variable level and use the built in properties (seen here: https://cmake.org/cmake/help/latest/manual/cmake-properties.7.html) to keep it compiler agnostic.
For Example:
set_target_properties(FooTarget PROPERTIES
CXX_STANDARD 17
CXX_EXTENSIONS OFF
etc..
)
You can keep that set(CMAKE_CXX_STANDARD 17)
for other compilers, like Clang and GCC. But for Visual Studio, it's useless.
If CMake still doesn't support this, you can do the following:
if(MSVC)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /std:c++17")
endif(MSVC)
Modern CMake propose an interface for this purpose target_compile_features
.
Documentation is here: Requiring Language Standards
Use it like this:
target_compile_features(${PROJECT_NAME} PRIVATE cxx_std_17)