495

In a GCC compiled project,

  • How do I run CMake for each target type (debug/release)?
  • How do I specify debug and release C/C++ flags using CMake?
  • How do I express that the main executable will be compiled with g++ and one nested library with gcc?
Peter Mortensen
  • 28,342
  • 21
  • 95
  • 123
Cartesius00
  • 21,471
  • 40
  • 115
  • 185

6 Answers6

743

With CMake, it's generally recommended to do an "out of source" build. Create your CMakeLists.txt in the root of your project. Then from the root of your project:

mkdir Release
cd Release
cmake -DCMAKE_BUILD_TYPE=Release ..
make

And for Debug (again from the root of your project):

mkdir Debug
cd Debug
cmake -DCMAKE_BUILD_TYPE=Debug ..
make

Release / Debug will add the appropriate flags for your compiler. There are also RelWithDebInfo and MinSizeRel build configurations.


You can modify/add to the flags by specifying a toolchain file in which you can add CMAKE_<LANG>_FLAGS_<CONFIG>_INIT variables, e.g.:

set(CMAKE_CXX_FLAGS_DEBUG_INIT "-Wall")
set(CMAKE_CXX_FLAGS_RELEASE_INIT "-Wall")

See CMAKE_BUILD_TYPE for more details.


As for your third question, I'm not sure what you are asking exactly. CMake should automatically detect and use the compiler appropriate for your different source files.

Alex Reinking
  • 6,342
  • 2
  • 28
  • 47
kb1ooo
  • 7,540
  • 1
  • 12
  • 9
  • 4
    You can also do a `cmake -i ..` instead, so cmake will run interactively, asking you which type of build you want (None, Release, Debug, MinSizeRel, RelWithDebInfo). – thiagowfx Dec 10 '16 at 17:48
  • 6
    @thiagowfx `-i` option results in this error message: `The "cmake -i" wizard mode is no longer supported.`. I'm using cmake 3.7.1 – Philipp Claßen Jan 04 '17 at 21:01
  • 5
    Nice observation. It seems it was deprecated since version `3.0.0`. [Reference](https://cmake.org/cmake/help/v3.0/release/3.0.0.html#deprecated-and-removed-features). – thiagowfx Jan 09 '17 at 16:02
  • 9
    This is NOT an out of source build if you are creating a sub-directory! It is advised to create the build directory outside/above the source directory. – Victor Lamoine Feb 19 '17 at 10:50
  • Note that if `CMAKE_BUILD_TYPE` is not set, cmake won't choose any default build type, hence the generated compiler command line won't be matching any build configuration. – david Mar 28 '18 at 19:12
  • Where can I see the default Compiler Flags and Definitions for Cmake in Release mode? Does it define `_DNDEBUG` automatically? – Royi Sep 01 '18 at 13:31
  • This seems a bit wasteful as much of what CMake discovers is the same for all builds. Also this gets a bit tedious when you have multiple configurations outside the release/debug choice. For example: > mkdir able && ( cd able && cmake -C ../config/able.cmake ../sources ) > mkdir baker && ( cd baker && cmake -C ../config/baker.cmake ../sources ) > mkdir charlie && ( cd charlie && cmake -C ../config/charlie.cmake ../sources ) Doubling for release/debug is tedious. > mkdir able.debug && ( cd able.debug && cmake -C ../config/able.cmake ../sources ) (etc.) – Preston L. Bannister Apr 05 '19 at 05:00
  • Thanks for this answer. I keep coming back because I always forget when it comes to changing config from debug to release (and vice versa). Good reference. I bookmarked it. – thang Aug 17 '19 at 21:40
  • **NEVER** set `CMAKE__FLAGS_` from the toolchain file! Instead, set `CMAKE__FLAGS__INIT`. – Alex Reinking Jun 18 '20 at 23:37
26

For debug/release flags, see the CMAKE_BUILD_TYPE variable (you pass it as cmake -DCMAKE_BUILD_TYPE=value). It takes values like Release, Debug, etc.

https://gitlab.kitware.com/cmake/community/wikis/doc/cmake/Useful-Variables#compilers-and-tools

cmake uses the extension to choose the compiler, so just name your files .c.

You can override this with various settings:

For example:

set_source_files_properties(yourfile.c LANGUAGE CXX) 

Would compile .c files with g++. The link above also shows how to select a specific compiler for C/C++.

S.S. Anne
  • 13,819
  • 7
  • 31
  • 62
duncan
  • 5,539
  • 2
  • 26
  • 24
21

Instead of manipulating the CMAKE_CXX_FLAGS strings directly (which could be done more nicely using string(APPEND CMAKE_CXX_FLAGS_DEBUG " -g3") btw), you can use add_compile_options:

add_compile_options(
  "-Wall" "-Wpedantic" "-Wextra" "-fexceptions"
  "$<$<CONFIG:DEBUG>:-O0;-g3;-ggdb>"
)

This would add the specified warnings to all build types, but only the given debugging flags to the DEBUG build. Note that compile options are stored as a CMake list, which is just a string separating its elements by semicolons ;.

Peter Bloomfield
  • 5,009
  • 22
  • 34
sebastian
  • 1,886
  • 17
  • 20
  • 2
    Won't `list(APPEND CMAKE_CXX_FLAGS_DEBUG "-g3")` add a semicolon before -g3 terminated the command and starting a new command -g3 which will surely fail? – cburn11 Sep 14 '18 at 13:46
  • You're right `CMAKE_CXX_FLAGS` is *not* a cmake list but a string of space-separated command line flags. I find that behavior inconsistent... – sebastian Sep 14 '18 at 15:29
  • add_compile_options() is neat. It is complemented by add_link_options() for when you need to add options to the linker too such as -fsanitize=address. – Bowie Owens Dec 18 '18 at 22:35
  • 6
    Is this still the appropriate way in 2020 / cmake 3.17? That last line looks nasty – Jay Apr 23 '20 at 07:28
  • @Jay kinda. It is correct to use generator expressions. But the semi-colon thing isn't necessary and is honestly hard to read. See my answer. Also add_compile_options isn't always what you meant. It's a big hammer. –  Nov 13 '20 at 16:13
16

A lot of the answers here are out of date/bad. So I'm going to attempt to answer it better. Granted I'm answering this question in 2020, so it's expected things would change.


How do I run CMake for each target type (debug/release)?

First off Debug/Release are called configurations in cmake (nitpick).

If you are using a single configuration generator (Ninja/Unix-Makefiles)

Then you need a build folder for each configuration.

Like this:

# Configure the build
cmake -S . -B build/Debug -D CMAKE_BUILD_TYPE=Release

# Actually build the binaries
cmake --build build/Debug

For multi-configuration generators it's slightly different (Ninja Multi-Config, Visual Studio)

# Configure the build
cmake -S . -B build

# Actually build the binaries
cmake --build build --config Debug

If you are wondering why this is necessary it's because cmake isn't a build system. It's a meta-build system (IE a build system that build's build systems). This is basically the result of handling build systems that support multiple-configurations in 1 build. If you'd like a deeper understanding I'd suggest reading a bit about cmake in Craig Scott's book "Professional CMake: A Practical Guide


How do I specify debug and release C/C++ flags using CMake?

The modern practice is to use target's and properties.

Here is an example:

add_library(foobar)

# Add this compile definition for debug builds, this same logic works for
# target_compile_options, target_link_options, etc.
target_compile_definitions(foobar PRIVATE
    $<$<CONFIG:Debug>:
        FOOBAR_DEBUG=1
    >
)

NOTE: How I'm using generator expressions to specify the configuration! Using CMAKE_BUILD_TYPE will result in bad builds for any multi-configuration generator!

Further more sometimes you need to set things globally and not just for one target. Use add_compile_definitions, add_compile_options, etc. Those functions support generator expressions. Don't use old style cmake unless you have to (that path is a land of nightmares)


How do I express that the main executable will be compiled with g++ and one nested library with gcc?

Your last question really doesn't make sense.

9

// CMakeLists.txt : release

set(CMAKE_CONFIGURATION_TYPES "Release" CACHE STRING "" FORCE)

// CMakeLists.txt : debug

set(CMAKE_CONFIGURATION_TYPES "Debug" CACHE STRING "" FORCE)
sailfish009
  • 1,790
  • 1
  • 17
  • 26
  • 16
    i don't understand why is this get down voted, it is real code which used in production, btw i don't care. – sailfish009 Feb 02 '18 at 00:26
  • 8
    Maybe because according to the CMake docs ``CMAKE_CONFIGURATION_TYPES`` contains the possible values for ``CMAKE_BUILD_TYPE``. So you should set the latter as the other answers suggest. Maybe your solution works because it limits the possible choices to the one you'd like to have. – bjhend Feb 21 '18 at 16:28
  • 5
    Upvote because this will work. I love me some CMake but there are quirks and sometimes you need to use big hammer to make things work. I have some projects that for one reason or another will reject the command line flag. – cory.todd May 16 '18 at 17:30
  • Here's some additional information on why the setting may not work: https://stackoverflow.com/a/24470998/3196753 – tresf Mar 26 '19 at 01:49
9

If you want to build a different configuration without regenerating if using you can also run cmake --build {$PWD} --config <cfg> For multi-configuration tools, choose <cfg> ex. Debug, Release, MinSizeRel, RelWithDebInfo

https://cmake.org/cmake/help/v2.8.11/cmake.html#opt%3a--builddir

Russel Waters
  • 91
  • 1
  • 4