Introduction
CMake is a build system generator that produces native build files (Makefiles, Ninja files, Visual Studio projects, Xcode projects) from a platform-independent configuration language. It has become the de facto standard for C and C++ projects, used by organizations from individual developers to large companies. CMake handles dependency discovery, compiler configuration, and cross-platform builds with a single set of CMakeLists.txt files.
What CMake Does
- Generates native build systems for Make, Ninja, Visual Studio, Xcode, and others
- Discovers system libraries and headers with
find_package()modules - Supports cross-compilation through toolchain files
- Manages build configurations (Debug, Release, RelWithDebInfo) across platforms
- Provides CTest for test execution and CPack for packaging installers
Architecture Overview
CMake runs in two phases: configure and generate. During configuration, it reads CMakeLists.txt files, evaluates variables and conditions, finds dependencies, and builds an internal representation of targets and their relationships. During generation, it writes out the native build files for the chosen generator (e.g., Unix Makefiles, Ninja). The actual compilation is then handled by the native build tool, not by CMake itself.
Self-Hosting & Configuration
- Install via system package manager, Homebrew, pip (
pip install cmake), or download from cmake.org - Write
CMakeLists.txtat the root of your project withproject(),add_executable(), andtarget_link_libraries() - Use out-of-source builds:
cmake -B build -S .keeps generated files separate from source - Configure presets in
CMakePresets.jsonfor reproducible builds across team members - Set toolchain files with
-DCMAKE_TOOLCHAIN_FILE=...for cross-compilation
Key Features
- CMake Presets standardize build configurations in a shareable JSON file
- Modern target-based approach with
target_link_libraries()propagates include paths and compile flags - FetchContent module downloads and builds external dependencies at configure time
- Generator expressions allow conditional logic evaluated at build time, not configure time
- First-class support for C, C++, CUDA, Fortran, ASM, Objective-C, and Swift
Comparison with Similar Tools
- Meson — simpler syntax and faster for smaller projects; CMake has broader IDE and ecosystem support
- Bazel — hermetic builds for monorepos; CMake is more portable and does not require a server
- Autotools — the traditional Unix build system; CMake is more cross-platform and easier to maintain
- Premake — Lua-based generator; CMake has a much larger community and package ecosystem
- xmake — newer Lua-based build system; CMake remains the most widely adopted for C/C++
FAQ
Q: What is the difference between CMake and Make? A: CMake generates Makefiles (or other build files). Make executes them. CMake is the meta-build system.
Q: Should I use CMake Presets? A: Yes. Presets (introduced in CMake 3.19) let you define configure, build, and test settings in a versioned JSON file, replacing ad-hoc command-line flags.
Q: How do I add a third-party library?
A: Use find_package() for system-installed libraries or FetchContent to download and build from source during configuration.
Q: Does CMake support header-only libraries?
A: Yes. Declare an INTERFACE library with add_library(mylib INTERFACE) and attach include directories to it.