cmake -DCMAKE_BUILD_TYPE=Release: set Debug or Release builds
- tool
- CMake
- command
- cmake
- flag
- -DCMAKE_BUILD_TYPE=Debug|Release|RelWithDebInfo|MinSizeRel
- default
- empty (no optimization flags) unless the toolchain or the CMAKE_BUILD_TYPE environment variable sets one
- since
- CMake 2.x
cmake -S . -B build -DCMAKE_BUILD_TYPE=Release configures an optimized build. The variable selects one of the standard configurations (Debug, Release, RelWithDebInfo, MinSizeRel) and with it the compiler flags in CMAKE_<LANG>_FLAGS_<CONFIG>. It only applies to single-config generators (Ninja, Unix Makefiles). Multi-config generators (Visual Studio, Xcode, Ninja Multi-Config) ignore it and take the configuration at build time: cmake --build build --config Release.
Single-config vs multi-config
file(GENERATE) writes one file per configuration that the generator knows about, which shows the difference without needing a compiler:
cat > CMakeLists.txt <<'EOF'
cmake_minimum_required(VERSION 3.20)
project(demo NONE)
message(STATUS "CMAKE_BUILD_TYPE='${CMAKE_BUILD_TYPE}'")
file(GENERATE OUTPUT config-$<CONFIG>.txt CONTENT "built as $<CONFIG>\n")
EOF
cmk() { uv run -q --no-project --python 3.13 --with cmake==4.4.4 --with ninja==1.13.0 cmake "$@" | grep BUILD_TYPE; }
echo "--- Ninja, no build type"; cmk -S . -B b1 -G Ninja; ls b1 | grep config
echo "--- Ninja, Release"; cmk -S . -B b2 -G Ninja -DCMAKE_BUILD_TYPE=Release; ls b2 | grep config
echo "--- Ninja Multi-Config"; cmk -S . -B b3 -G "Ninja Multi-Config"; ls b3 | grep configOutput
--- Ninja, no build type -- CMAKE_BUILD_TYPE='' config-.txt --- Ninja, Release -- CMAKE_BUILD_TYPE='Release' config-Release.txt --- Ninja Multi-Config -- CMAKE_BUILD_TYPE='' config-Debug.txt config-RelWithDebInfo.txt config-Release.txt
Without CMAKE_BUILD_TYPE, a single-config build has an empty configuration: no -O2, no -g, just the base flags. The multi-config generator creates all configurations and ignores the variable.
Build types
| Value | GCC/Clang flags (defaults) | MSVC flags (defaults) | Use for |
|---|---|---|---|
| Debug | -g | /Zi /Ob0 /Od /RTC1 | debugging |
| Release | -O3 -DNDEBUG | /O2 /Ob2 /DNDEBUG | production |
| RelWithDebInfo | -O2 -g -DNDEBUG | /Zi /O2 /Ob1 /DNDEBUG | profiling, release with symbols |
| MinSizeRel | -Os -DNDEBUG | /O1 /Ob1 /DNDEBUG | small binaries |
The exact default flags depend on the compiler and CMake version; print them with cmake -LA build | grep CMAKE_CXX_FLAGS.
Commands
# single-config (Ninja, Makefiles): choose at configure time
cmake -S . -B build -G Ninja -DCMAKE_BUILD_TYPE=Release
cmake --build build
# multi-config (Visual Studio, Xcode, Ninja Multi-Config): choose at build time
cmake -S . -B build -G "Ninja Multi-Config"
cmake --build build --config Release--config is harmless with single-config generators, so scripts that must work with both can pass both options. Since CMake 3.22, the CMAKE_BUILD_TYPE environment variable provides a default when the cache variable is not set.