Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why won't CMake add a language standard compilation flag to a target via CMAKE_CXX_STANDARD created before the definition of that variable?

Tags:

c++

cmake

c++20

I'm using cmake version 3.22.1 and c++ (Ubuntu 11.3.0-1ubuntu1~22.04) 11.3.0

and a very minimalistic CMakeLists.txt

I can't make CMAKE use C++20.

Setting

set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD_REQUIRED True)

leads to no flag being present in the output.

[ 50%] Building CXX object CMakeFiles/Executable.dir/tutorial.cxx.o /usr/bin/c++ -MD -MT CMakeFiles/Executable.dir/tutorial.cxx.o -MF CMakeFiles/Executable.dir/tutorial.cxx.o.d -o CMakeFiles/Executable.dir/tutorial.cxx.o -c /media/ruby/SHARED/Diverses/Programmieren/cmake_tutorial/tutorial.cxx

Using this however:

set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++20")

[ 50%] Building CXX object CMakeFiles/Executable.dir/tutorial.cxx.o /usr/bin/c++ -std=c++20 -MD -MT CMakeFiles/Executable.dir/tutorial.cxx.o -MF CMakeFiles/Executable.dir/tutorial.cxx.o.d -o CMakeFiles/Executable.dir/tutorial.cxx.o -c /media/ruby/SHARED/Diverses/Programmieren/cmake_tutorial/tutorial.cxx

works flawlessly. Any idea what I'm doing wrong?

The full CMakeLists.txt

# First line, every project needs it
cmake_minimum_required(VERSION 3.22.1)

# Specifies the name of the project
project(example_project)

# Tell cmake to create executable using specified source code files
add_executable(Executable tutorial.cxx)

# This part adds the flag correcly
# set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++20")

# This does not
set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD_REQUIRED True)
like image 314
Cramstyler Avatar asked Sep 02 '25 16:09

Cramstyler


2 Answers

The docs for CMAKE_CXX_STANDARD state:

Default value for CXX_STANDARD target property if set when a target is created.

You set the default-initializer variable after the creation of the target you wanted it to apply for. Move the varible definition to go before the creation of the target you want it to apply to. Or just use target_compile_features.

setting CMAKE_CXX_FLAGS after the creation of a target works because CMAKE_CXX_FLAGS works differently. See the docs.

The flags in this variable will be passed to the compiler before those in the per-configuration CMAKE_<LANG>_FLAGS_<CONFIG> variant, and before flags added by the add_compile_options() or target_compile_options() commands.

The contents of CMAKE_CXX_STANDARD are copied to a target property at the time the target is created/defined, and that target property does not watch CMAKE_CXX_STANDARD to mirror changes. CMAKE_CXX_FLAGS is managed as its own thing and is added to the final list of compile flags for a source file when that final list is created.

like image 135
starball Avatar answered Sep 05 '25 05:09

starball


Order is important, this doesn't work:

add_executable(Executable tutorial.cxx)
set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD_REQUIRED True)

And this one works as expected:

set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD_REQUIRED True)
add_executable(Executable tutorial.cxx)
like image 33
Olaf Dietsche Avatar answered Sep 05 '25 07:09

Olaf Dietsche