CMake is a cross‑platform, open‑source build‑system generator.
It produces native build files (Ninja
, Makefiles
, Visual Studio
solutions, etc.), letting you describe your project once in portable CMakeLists.txt
files. As of April 10 2025 the latest stable version is CMake 4.0.1.
cmake -S . -B build
reads your CMakeLists.txt
, inspects compilers, sets cache variables and generates buildsystem files.cmake --build build [--target install]
invokes the native tool (ninja
, make
, msbuild
, …).Generator
: Backend chosen with -G
(e.g., Ninja Multi‑Config
).Target
: Logical build unit (add_executable
, add_library
).Property
: Key‑value metadata attached to a target, file, directory, or global scope.Policy
: Version‑controlled behavior switch; OLD behavior removed for CMP0000–CMP0065 in CMake 4.0 .sudo apt install cmake
(Deb / Ubuntu), dnf install cmake
(Fedora), or pacman -S cmake
(Arch).brew install cmake
or port install cmake
.winget install kitware.cmake
or choco install cmake
.Download self‑extracting installers or .zip
/.tar.gz
archives from cmake.org — always grab the latest 4.0.1 release.
git clone https://github.com/kitware/cmake.git
cd cmake && ./bootstrap && make -j$(nproc) && sudo make install
# 1 · Configure
cmake -S . -B build -G Ninja -D CMAKE_BUILD_TYPE=Release
# 2 · Build
cmake --build build
# 3 · Install (optional)
cmake --install build --prefix /usr/local
Edit CMakeLists.txt
→ run cmake -S . -B build
again. CMake re‑evaluates only changed files.
CMakePresets.json
){
"version": 4,
"configurePresets": [
{
"name": "ninja-release",
"generator": "Ninja",
"binaryDir": "${sourceDir}/build",
"cacheVariables": {
"CMAKE_BUILD_TYPE": "Release"
}
}
]
}
Run cmake --preset ninja-release
to configure; cmake --build --preset ninja-release
to build.
CMakeLists.txt
cmake_minimum_required(VERSION 3.20)
project(hello LANGUAGES CXX)
add_executable(hello src/main.cpp)
target_compile_features(hello PRIVATE cxx_std_20)
set()
: set(VERSION_MAJOR 1)
set(SOURCES a.cpp;b.cpp;c.cpp)
${var}
; environment via $ENV{HOME}
.if (CMAKE_SYSTEM_NAME STREQUAL "Windows")
set(PLATFORM_DEFINES WIN32_LEAN_AND_MEAN)
endif()
Evaluate during generation: $<CONFIG:Debug>
, $<TARGET_FILE:foo>
.
add_executable()
for apps.add_library()
(STATIC
, SHARED
, INTERFACE
, OBJECT
).Prefer target_*()
commands:
target_include_directories(hello
PUBLIC ${PROJECT_SOURCE_DIR}/include) # Propagates to dependents
target_link_libraries(hello
PRIVATE fmt::fmt) # Link only for this target
Provide header‑only packages or rename targets:
add_library(spdlog::spdlog ALIAS spdlog)
target_compile_features(hello PUBLIC cxx_std_23)
target_compile_options(hello PRIVATE -Wall -Wextra)
target_compile_definitions(hello PUBLIC VERSION_MAJOR=${VERSION_MAJOR})
find_package()
Searches for package config files (FooConfig.cmake
) or FindFoo.cmake
modules.
include(FetchContent)
FetchContent_Declare(
json
GIT_REPOSITORY https://github.com/nlohmann/json.git
GIT_TAG v3.11.3
)
FetchContent_MakeAvailable(json)
For large downloads or pre‑built binaries use ExternalProject_Add()
. Modern alternative: CPM.cmake. vcpkg integrates via -DCMAKE_TOOLCHAIN_FILE=[vcpkg]/scripts/buildsystems/vcpkg.cmake
.
# toolchain-arm64-linux.cmake
set(CMAKE_SYSTEM_NAME Linux)
set(CMAKE_SYSTEM_PROCESSOR aarch64)
set(CMAKE_C_COMPILER aarch64-linux-gnu-gcc)
set(CMAKE_CXX_COMPILER aarch64-linux-gnu-g++)
Invoke: cmake -S . -B build -DCMAKE_TOOLCHAIN_FILE=toolchain-arm64-linux.cmake
{
"configurePresets": [
{
"name": "rpi-release",
"generator": "Ninja",
"binaryDir": "${sourceDir}/build/rpi",
"toolchainFile": "toolchain-arm64-linux.cmake",
"cacheVariables": { "CMAKE_BUILD_TYPE": "Release" }
}
]
}
enable_testing()
add_test(NAME unit
COMMAND hello --self-test)
Run ctest -V
. Combine with --output-on-failure
for detailed logs.
Submit results: ctest -S dashboard.cmake
.
include(CPack) # after install() commands
set(CPACK_GENERATOR "TGZ;DEB") # rpm, nsis, dmg, etc.
set(CPACK_PACKAGE_CONTACT "you@example.com")
Generate packages: cpack -G DEB --config ./build/CPackConfig.cmake
add_custom_command(
OUTPUT generated.cpp
COMMAND python codegen.py -o generated.cpp
DEPENDS codegen.py
)
add_custom_target(generate_sources DEPENDS generated.cpp)
IDE tooling (e.g., VS Code CMake Tools) reads .cmake/api/v1
replies for semantic project data.
Enable the new --profile
flag (≥ 4.0) to emit JSON timing data.
CMake 4.0 permanently deletes OLD modes for policies CMP0000–CMP0065
.
Use cmake_policy(SET CMP0000 NEW)
where necessary .
cmake -P cmake_upgrade_test.cmake
to scan for deprecated commands.include_directories()
/link_libraries()
in favor of target‑scoped variants.cmake‑language‑server
provides completion & linting for .cmake
files.