Why my CMake does not add CMAKE_CXX_FLAGS_DEBUG to CMAKE_CXX_FLAGS?

Viewed 1516

I suppose that using cmake with CMAKE_BUILD_TYPE adds appropriate compiler flag to CMAKE_CXX_FLAGS. However, once I typed the following command and then see the content of CMAKE_CXX_FLAGS, nothing expected was added.

mkdir build
cd build
cmake .. -DCMAKE_BUILD_TYPE=DEBUG

Below is the snippet of my CMakeLists.txt.

... #version and project name
set(CMAKE_CXX_FLAGS "-Wall")
set(CMAKE_CXX_FLAGS_DEBUG "-g3")
message(${CMAKE_CXX_FLAGS})

From the message, I expected it to show -Wall -g3.

But what was shown was only -Wall, seeming that CMAKE_CXX_FLAGS_DEBUG was not added to CMAKE_CXX_FLAGS as opposed to the explanation given in https://cmake.org/cmake/help/v3.0/variable/CMAKE_BUILD_TYPE.html. It says that For example, in a build tree configured to build type Debug, CMake will see to having CMAKE_C_FLAGS_DEBUG settings get added to the CMAKE_C_FLAGS settings. See also CMAKE_CONFIGURATION_TYPES.

In my case, which one was indeed used, CMAKE_CXX_FLAGS or CMAKE_CXX_FLAGS_DEBUG?

2 Answers

CMAKE_CXX_FLAGS is just a variable. You set -Wall to the variable, so -Wall is what the variable contains.

The documentation is misleading. CMAKE_CXX_FLAGS_DEBUG is not added into the CMAKE_CXX_FLAGS variable. The content of CMAKE_CXX_FLAGS_DEBUG is added to the content of CMAKE_CXX_FLAGS variable, and the result is given to the compiler (not stored in the CMAKE_CXX_FLAGS variable).

In my case, which one was indeed used, CMAKE_CXX_FLAGS or CMAKE_CXX_FLAGS_DEBUG?

Both are used in your case (assuming CMAKE_BUILD_TYPE is case-insensitive).

CMAKE_CXX_FLAGS is used for all builds and CMAKE_CXX_FLAGS_DEBUG is used when -DCMAKE_BUILD_TYPE=Debug.


The author of a CMakeLists.txt file should avoid modifying these variables and instead use target_compile_options if necessary.

CMake does not merge your _FLAGS variables immediately at the CMake configure stage (when you print the variable using message()). Instead, you can see how CMake treated these settings by running:

make VERBOSE=1

then examining the output to see if the appropriate flags are being passed to the compiler.

In general, manually manipulating the _FLAGS variables like this is discouraged. When necessary, it is typical to append your flags (as commented) to the existing flags, rather than over-writing them:

set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall")

However, with newer versions of CMake, it is best practice to apply compilation flags using a target-based approach. This aligns well with sound, object-oriented, software engineering principles, rather than setting flags in a blanketed manner. As such, you could use target_compile_options to set these flags where appropriate instead:

target_compile_options(YourTarget PRIVATE 
    -Wall 
    $<$<CONFIG:Debug>:-g3>
)
Related