Overwriting flag set in CMAKE_CXX_FLAGS by flag set in CMAKE_CXX_FLAGS_DEBUG

Viewed 66

On my system, CMake populates CMAKE_CXX_FLAGS with O2 optimization flags and and I add O0 flags for the debug configurations, such that I find this in my CMakeCache.txt:

//Flags used by the CXX compiler during all build types.
CMAKE_CXX_FLAGS:STRING=-O2

//Flags used by the CXX compiler during DEBUG builds.
CMAKE_CXX_FLAGS_DEBUG:STRING=-O0

According to the documentation of CMake, the configuration dependent flags are appended. The issue with this seems to be, that the 02 flag appears to take precedence over the O0 flag. Is there a way to configure CMake, possibly from cli call to it, such that it uses O0 instead?

1 Answers

This is indeed very confusing so I set up a very small test.

$ cat CMakeLists.txt 
cmake_minimum_required( VERSION 3.0 )
project(test)
add_executable( test test.cpp )

$ cat test.cpp
int main() {
}

Then I build with default options and look at the resulting options. Check that the resulting flags are empty. In the command line, cmake adds "-MT -MD" for dependency checking.

$ mkdir build && cd build
$ cmake ..
$ make VERBOSE=1
/usr/bin/c++    -MD -MT ... -c /tmp/test/test.cpp
$ grep ^CMAKE_CXX_FLAGS CMakeCache.txt
CMAKE_CXX_FLAGS:STRING=
CMAKE_CXX_FLAGS_DEBUG:STRING=-g
CMAKE_CXX_FLAGS_MINSIZEREL:STRING=-Os -DNDEBUG
CMAKE_CXX_FLAGS_RELEASE:STRING=-O3 -DNDEBUG
CMAKE_CXX_FLAGS_RELWITHDEBINFO:STRING=-O2 -g -DNDEBUG

Now compiling for release mode. Check that the options in the cache are exactly the same but cmake is now using the release options.

$ rm -rf * 
$ cmake -DCMAKE_BUILD_TYPE=release ..
$ make VERBOSE=1
/usr/bin/c++ -O3 -DNDEBUG -MD -MT ... -c /tmp/test/test.cpp
$ grep ^CMAKE_CXX_FLAGS CMakeCache.txt 
CMAKE_CXX_FLAGS:STRING=
CMAKE_CXX_FLAGS_DEBUG:STRING=-g
CMAKE_CXX_FLAGS_MINSIZEREL:STRING=-Os -DNDEBUG
CMAKE_CXX_FLAGS_RELEASE:STRING=-O3 -DNDEBUG
CMAKE_CXX_FLAGS_RELWITHDEBINFO:STRING=-O2 -g -DNDEBUG

Now let's change the CMAKE_CXX_FLAGS variable directly. The option has been prepended to the make command line but in the cache file everything else remains the same.

$ rm -rf *
$ cmake -DCMAKE_BUILD_TYPE=release -DCMAKE_CXX_FLAGS="-O1" ..
$ make VERBOSE=1
/usr/bin/c++   -O1 -O3 -DNDEBUG -MD -MT ... -c /tmp/test/test.cpp
$ grep ^CMAKE_CXX_FLAGS CMakeCache.txt 
CMAKE_CXX_FLAGS:STRING=-O1
CMAKE_CXX_FLAGS_DEBUG:STRING=-g
CMAKE_CXX_FLAGS_MINSIZEREL:STRING=-Os -DNDEBUG
CMAKE_CXX_FLAGS_RELEASE:STRING=-O3 -DNDEBUG
CMAKE_CXX_FLAGS_RELWITHDEBINFO:STRING=-O2 -g -DNDEBUG

Let's now change the CMAKE_CXX_FLAGS_RELEASE variable directly to see what happens. Looks like now we were able to replace the optimization flags with our own.

$ rm -rf *
$ cmake -DCMAKE_BUILD_TYPE=release -DCMAKE_CXX_FLAGS_RELEASE="-O1" ..
$ make VERBOSE=1
/usr/bin/c++   -O1 -MD -MT ... -c /tmp/test/test.cpp
$ grep ^CMAKE_CXX_FLAGS CMakeCache.txt 
CMAKE_CXX_FLAGS:STRING=
CMAKE_CXX_FLAGS_DEBUG:STRING=-g
CMAKE_CXX_FLAGS_MINSIZEREL:STRING=-Os -DNDEBUG
CMAKE_CXX_FLAGS_RELEASE:STRING=-O1
CMAKE_CXX_FLAGS_RELWITHDEBINFO:STRING=-O2 -g -DNDEBUG

cmake also provides a CMAKE_<LANGUAGE>_FLAGS_<BUILDMODE>_INIT option. Let's see what is the impact.

$ rm -rf * 
$ cmake -DCMAKE_BUILD_TYPE=release -DCMAKE_CXX_FLAGS_RELEASE_INIT="-O1" ..
$ make VERBOSE=1
/usr/bin/c++   -O1 -O3 -DNDEBUG -MD -MT ... -c /tmp/test/test.cpp
$ grep ^CMAKE_CXX_FLAGS CMakeCache.txt 
CMAKE_CXX_FLAGS:STRING=
CMAKE_CXX_FLAGS_DEBUG:STRING=-g
CMAKE_CXX_FLAGS_MINSIZEREL:STRING=-Os -DNDEBUG
CMAKE_CXX_FLAGS_RELEASE:STRING=-O1 -O3 -DNDEBUG
CMAKE_CXX_FLAGS_RELEASE_INIT:UNINITIALIZED=-O1
CMAKE_CXX_FLAGS_RELWITHDEBINFO:STRING=-O2 -g -DNDEBUG

So the effect of those CMAKE_CXX_FLAGS_<MODE>_INIT variables is the same as setting CMAKE_CXX_FLAGS, it prepends them to the command line, but you can configure individually for each mode - release, debug, relwithdebinfo.

So to the point of your question, setting CMAKE_CXX_FLAGS_DEBUG directly should override the other default options if you compile in debug mode.

Related