swertz
swertz

Reputation: 121

Conflict on c++ standard with cmake

I'm having some issues with setting the C++ standard for my project built with CMake. The code heavily uses C++11 features, so up to now I was doing:

set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)

Now, since recent GCC versions use C++14 by default, I end up having to link with libraries built with C++14 as public requirement, and there is a conflict when trying to build using strictly C++11.

So, the goal is to require at least the C++11 standard, but using the default compiler version if it is more recent.

I've tried with

target_compile_features(myLib PUBLIC cxx_std_11)

but CMake ends up adding the -std=c++11 flag, which is confusing because the documentation explictly says

CMake will ensure the compiler is invoked in a mode that is aware of C++ 11 (or above), adding flags such as -std=gnu++11 if necessary

I've also tried using the CMAKE_CXX_STANDARD_COMPUTED_DEFAULT internal variable, but that is cumbersome since "98" is greater than "11".

It is certainly possible to get it working using that variable or using the check_cxx_compiler_flag() function, and testing the different cases, but I was hoping that there would be a simpler way to achieve this in a day and age where new standards arrive every three years...

Upvotes: 6

Views: 1594

Answers (1)

Dredok
Dredok

Reputation: 805

I know this is an old question, but anyways: You are on the right path, just use target_compile_features for the libraries you declare in your CMakeLists projects. There should be no problem linking a c++14 library with a c++11 library if you are using the same GCC version (it doesn't matter what -std=... do you put on each library).

So, if you have libA, libB and libC and you can just do this:

target_compile_features(libA PUBLIC cxx_std_11)
target_compile_features(libB PUBLIC cxx_std_14)
target_compile_features(libC PUBLIC cxx_std_17)

If for some reason the compiler version needed to be different, then I guess you should be able to link them if you can build shared libraries instead of static libraries.

Further clarification regarding cxx extensions and standard: If extensions want to be avoided (ie compiling with c++11 instead of gnu++11) one could set CMAKE_CXX_EXTENSIONS OFF

set(CMAKE_CXX_EXTENSIONS OFF)

Default behavior is to have CXX extensions enabled. You need to set this before the target is created.

Simple example without extensions allowed:

cmake_minimum_required(VERSION 3.16)

project(test-poc)
set(CMAKE_CXX_EXTENSIONS OFF)

add_executable(main main.cpp)

target_compile_features(main PRIVATE cxx_std_17)

we add CMAKE_CXX_EXTENSIONS OFF before creating the target, so CMake will choose -std=c++17 instead of -std=gnu++17. If we remove that line, CMake will chose -std=gnu++17

See: https://cmake.org/cmake/help/latest/prop_tgt/CXX_EXTENSIONS.html#prop_tgt:CXX_EXTENSIONS

Upvotes: 5

Related Questions