Skip to content

/flags/cmake/cmake-build-type

cmake -DCMAKE_BUILD_TYPE=Release: set Debug or Release builds

verified onenvironmentlocal · windows 10.0.26200 arm64 · GNU bash 5.3.15 (Git Bash)updated
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:

bash
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 config

Output

--- 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

ValueGCC/Clang flags (defaults)MSVC flags (defaults)Use for
Debug-g/Zi /Ob0 /Od /RTC1debugging
Release-O3 -DNDEBUG/O2 /Ob2 /DNDEBUGproduction
RelWithDebInfo-O2 -g -DNDEBUG/Zi /O2 /Ob1 /DNDEBUGprofiling, release with symbols
MinSizeRel-Os -DNDEBUG/O1 /Ob1 /DNDEBUGsmall binaries

The exact default flags depend on the compiler and CMake version; print them with cmake -LA build | grep CMAKE_CXX_FLAGS.

Commands

bash
# 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.

Sources