25

I'm trying to configure my build system so that my release builds don't have extra debugging included. But I can't find anywhere in the CMake documentation that lists which compiler flags are used by default per build type, and I'd rather not invent my own way of doing things.

Does this functionality already exist? Without resorting to trial and error, how can I determine what flags are used by default for the various build types?

mpontillo
  • 13,559
  • 7
  • 62
  • 90
  • 1
    Does this answer your question? [How to list all CMake build options and their default values?](https://stackoverflow.com/questions/16851084/how-to-list-all-cmake-build-options-and-their-default-values) – Marine Galantin Dec 06 '20 at 15:34
  • @MarineGalantin: A variable like `CMAKE_C_FLAGS_DEBUG` is not a CACHEd one, so it cannot be inspected by `cmake -LA` or by other CMake options. – Tsyvarev Dec 06 '20 at 17:54
  • see https://www.brianlheim.com/2018/04/09/cmake-cheat-sheet.html#build-types – Joe' Jan 15 '21 at 18:57

2 Answers2

44

This blog post has some helpful information, and this post describes some common anti-patterns.

The four build types that CMake includes out of the box are Release, Debug, RelWithDebInfo, and MinSizeRel. Correspondingly, CMake ships with default values for each defined build type in CMAKE_C_FLAGS_<buildType> and CMAKE_CXX_FLAGS_<buildType>.

If you want to find out the what the default values are for each build type, you can add the following statements to your CMakeLists.txt:

message("CMAKE_C_FLAGS_DEBUG is ${CMAKE_C_FLAGS_DEBUG}")
message("CMAKE_C_FLAGS_RELEASE is ${CMAKE_C_FLAGS_RELEASE}")
message("CMAKE_C_FLAGS_RELWITHDEBINFO is ${CMAKE_C_FLAGS_RELWITHDEBINFO}")
message("CMAKE_C_FLAGS_MINSIZEREL is ${CMAKE_C_FLAGS_MINSIZEREL}")

message("CMAKE_CXX_FLAGS_DEBUG is ${CMAKE_CXX_FLAGS_DEBUG}")
message("CMAKE_CXX_FLAGS_RELEASE is ${CMAKE_CXX_FLAGS_RELEASE}")
message("CMAKE_CXX_FLAGS_RELWITHDEBINFO is ${CMAKE_CXX_FLAGS_RELWITHDEBINFO}")
message("CMAKE_CXX_FLAGS_MINSIZEREL is ${CMAKE_CXX_FLAGS_MINSIZEREL}")

On my version of cmake (cmake version 2.8.12.1 on OS X), this prints the following values:

CMAKE_C_FLAGS_DEBUG is -g
CMAKE_C_FLAGS_RELEASE is -O3 -DNDEBUG
CMAKE_C_FLAGS_RELWITHDEBINFO is -O2 -g -DNDEBUG
CMAKE_C_FLAGS_MINSIZEREL is -Os -DNDEBUG

CMAKE_CXX_FLAGS_DEBUG is -g
CMAKE_CXX_FLAGS_RELEASE is -O3 -DNDEBUG
CMAKE_CXX_FLAGS_RELWITHDEBINFO is -O2 -g -DNDEBUG
CMAKE_CXX_FLAGS_MINSIZEREL is -Os -DNDEBUG

(as you can see, the sets of flags are the same for C and C++ by default.)

Be cautious, because the default build type is an empty string. So unless you specify a build type, none of the above applies. On the cmake mailing list, the following code was suggested (should be placed near the top of a top-level CMakeLists.txt, I imagine) for those who do not desire this behavior:

if (NOT CMAKE_BUILD_TYPE)
    message(STATUS "No build type selected, default to Release")
    set(CMAKE_BUILD_TYPE "Release")
endif()

However, this is not recommended, because it will break some mutli-configuration generators. (Better to set it inside a build script.)

(One of the blog posts above advocated using a shell alias to set -DCMAKE_BUILD_TYPE=Debug when cmake is first invoked instead.)

tastytea
  • 133
  • 4
mpontillo
  • 13,559
  • 7
  • 62
  • 90
  • 2
    All of the posts you've mentioned and your answer itself (the `if (NOT CMAKE_BUILD_TYPE)` part) will not work for multi-configuration generators. See my [answer](http://stackoverflow.com/a/24470998/2288008) –  Jul 16 '14 at 05:03
  • 2
    This [post](http://ecrafter.wordpress.com/2012/04/24/cmake-tutorial-part-2/) holds some anti-patterns itself, like building in-source (`cmake .`), setting compiler flags by add_definitions command (` add_definitions(-Wall -std=c++0x)`) and rewriting user-defined flags (set(CMAKE_CXX_FLAGS "-std=c++0x -Wall")) –  Jul 16 '14 at 05:07
  • @ruslo, thanks. I'll edit my answer to make it clear that checking if the build type is defined is not a portable solution. (I linked to the posts to give credit, since part of the answer was copy/pasted and then expanded upon.) – mpontillo Jul 16 '14 at 05:10
  • @ruslo, true, but I meant non-tainted defaults. ;-) By passing it in like that, they've either tainted it accidentally, or customized it intentionally... – mpontillo Jul 16 '14 at 05:15
  • 1
    If you want to check cmake default flags, you can see them in /usr/share/cmake-/Modules/Compiler/GNU.cmake file. – cloudrain21 May 08 '17 at 08:01
  • 1
    The default build type is initialized by the `project` command as of 3.22. For earlier versions, you can just add `AND NOT GENERATOR_IS_MULTI_CONFIG` to the condition. – John Freeman Jan 25 '22 at 16:16
1

You could also either:

  • List all built-in variables and grep the ones of interest:

    cmake -LAH .. | grep -C1 CMAKE_CXX_FLAGS
    

    as mentioned at: How to list all CMake build options and their default values? This gives:

    // Flags used by the CXX compiler during all build types.
    CMAKE_CXX_FLAGS:STRING=
    
    // Flags used by the CXX compiler during DEBUG builds.
    CMAKE_CXX_FLAGS_DEBUG:STRING=-g
    
    // Flags used by the CXX compiler during MINSIZEREL builds.
    CMAKE_CXX_FLAGS_MINSIZEREL:STRING=-Os -DNDEBUG
    
    // Flags used by the CXX compiler during RELEASE builds.
    CMAKE_CXX_FLAGS_RELEASE:STRING=-O3 -DNDEBUG
    
    // Flags used by the CXX compiler during RELWITHDEBINFO builds.
    CMAKE_CXX_FLAGS_RELWITHDEBINFO:STRING=-O2 -g -DNDEBUG
    

    Also note that:

    • by default, if -DMAKE_BUILD_TYPE is not passed, CMAKE_BUILD_TYPE is empty, and none of the extra CMAKE_CXX_FLAGS_XXX values are added, so that no flags are passed at all
    • the default GCC optimization level if -O0 as per man gcc, which is what takes effect for the build types that don't specify one (i.e. DEBUG)
  • do a verbose build for each build type of interest with make VERBOSE=1 which shows the full GCC CLI, e.g.:

    rm -rf build
    mkdir build
    cd build
    cmake -DCMAKE_BUILD_TYPE=Debug ..
    make VERBOSE=1
    

    and outputs something like:

    /usr/bin/cc -g -MD -MT CMakeFiles/main.dir/main.c.o -MF CMakeFiles/main.dir/main.c.o.d -o CMakeFiles/main.dir/main.c.o -c /home/ciro/cmake/option/main.c
    

    as explained at: How do I force make/GCC to show me the commands?

Tested on Ubuntu 22.10, CMake 3.24.2.

Ciro Santilli OurBigBook.com
  • 347,512
  • 102
  • 1,199
  • 985