CMake does not set the compiler option -std to gnu17 or c++17 although I set the target_compile_features to cxx_std_17

I updated the versions of GCC and CMake. After the update CMake no longer sets the right command line option for the c++ standard.

Here is how I set it:

add_library(project_options INTERFACE)
target_compile_features(project_options INTERFACE cxx_std_17)

and then I link to the project_options

target_link_libraries(app PRIVATE project_options)

With GCC 8.3 (on rhel) this sets the std compile flag to -std=gnu17

Now it is set to -std=c++11

If I set the compiler globally it works as expected:

set(CMAKE_CXX_STANDARD 17)

What am I missing? Or is this a bug in the new Tools?

My System:

  • GCC: 11.1.0
  • CMake: 3.20.2

This is a cross post from:
c++ - CMake does not set the compiler option -std to gnu17 or c++17 although I set the target_compile_features to cxx_std_17 - Stack Overflow

This has probably something to do with the fact that GCC11 defaults to -std=gnu++17
https://gcc.gnu.org/gcc-11/changes.html

1 Like

Interesting.

But why is then the standard set to c++11, if I use GCC11

This sounds like a regression to me. What version of CMake and GCC worked before?

It also did not work with the CMake Version 19.x and GCC11
But it worked with CMake Version 19.x and GCC10.2

OK, sounds like an environmental regression then. We are in the process of updating our CI to Fedora 34 which includes GCC 11, so this might show up there.

FYI @brad.king

1 Like

Thank you!
Could you write here once this is fixed?

This is working as designed. The cxx_std_17 feature is documented here. It does not mean “pass -std=c++17”. It means “run the compiler in a mode that supports C++17”. If the default compiler mode supports C++17, no flag is added.

gcc 11 defaults to C++17, and so does not need any -std= flag to satisfy cxx_std_17. On Fedora 34:

$ g++ --version
g++ (GCC) 11.1.1 20210428 (Red Hat 11.1.1-1)
$ g++ -x c++ /dev/null -E -dM | grep __cplusplus
#define __cplusplus 201703L
1 Like

Ok thank you, this makes perfect sense So why is there the c++11 flag after setting it? Maybe inherited from somewhere else? Can I override it?

Please post an example CMakeLists.txt file demonstrating how a -std=c++11 flag is showing up.

Thank you very much for your help!
The problem was that a fetched and build dependency sets the global standard to set(CMAKE_CXX_STANDARD 11).
But I think it is quite cumbersome that even though I require a target to be built with c++17 it is not. Is there another option then setting it globally?

I cannot reproduce that either:

$ cat ../CMakeLists.txt
cmake_minimum_required(VERSION 3.19)
project(Forum3299 CXX)
set(CMAKE_CXX_STANDARD 11)
add_library(example STATIC example.cxx)
target_compile_features(example PRIVATE cxx_std_17)

$ cmake ..
-- The CXX compiler identification is GNU 11.0.1
...

$  grep CMAKE_CXX_STANDARD_COMPUTED_DEFAULT CMakeFiles/*/CMakeCXXCompiler.cmake
set(CMAKE_CXX_STANDARD_COMPUTED_DEFAULT "17")

$ make VERBOSE=1 
...
/usr/bin/c++   -std=gnu++17 -o CMakeFiles/example.dir/example.cxx.o -c /.../example.cxx
...

I also wasn’t able to reproduce a minimal not working example.

I will try to figure out was causes the problem. Thank you for helping!

Your gcc was 11.0

It is v11.1 that come with c++17 as default

I came accross this today as well. It’s quite annoying because some of the lint (e.g. clangd) rely on compiler_commands.json for the settings. They don’t know gcc version and hence cannot infer --std

See my above reply. The behavior of cxx_std_## not always adding -std= is now also documented here. If you want explicit -std= options to appear in compile_commands.json, you need to set CMAKE_CXX_STANDARD to the desired standard level. That setting uses the given standard unless a cxx_std_## feature needs a higher one, and therefore should always pass a -std= flag.

1 Like