Est. 2000 Intermediate

CMake

A cross-platform build system generator that produces native build files for multiple platforms and compilers, created by Kitware for the Insight Toolkit project.

Created by Bill Hoffman (Kitware)

Paradigm Imperative, Declarative
Typing N/A (Build Tool)
First Appeared 2000
Latest Version 4.3.1 (2026)

CMake is a cross-platform build system generator created by Kitware. Rather than building software directly, CMake generates native build files for the user’s platform of choice – Makefiles, Ninja files, Visual Studio solutions, Xcode projects, and more. Originally developed to solve the cross-platform build challenges of a government-funded medical imaging project, CMake has grown to become the dominant build system in the C and C++ ecosystem, used by projects ranging from KDE and LLVM to Qt and Blender.

History & Origins

Background and Motivation

In 1999, Kitware was contracted by the U.S. National Library of Medicine to develop the Insight Segmentation and Registration Toolkit (ITK), a large-scale medical image analysis library. The project needed to build reliably across multiple platforms – Linux, Windows, and macOS – using each platform’s native compilers and development environments. The existing build tools were inadequate: Make was Unix-centric, and autotools had poor support for Windows and generated no IDE project files.

Kitware had prior experience with this problem. Their Visualization Toolkit (VTK) used a tool called pcmaker, developed by Ken Martin, which converted Unix Makefiles to Windows NMake files. This approach required developers to check in platform-specific binary executables when adding libraries and offered no IDE support. The TargetJr system they had previously worked with had gone through imake and gmake before reaching similar limitations.

Creation and First Release

Bill Hoffman, a co-founder of Kitware, designed CMake to address all of these shortcomings. The core requirements were clear: depend only on a C++ compiler, support native IDE project file generation (particularly Visual Studio), use a single input format across all platforms, and detect system capabilities at configure time rather than hard-coding platform differences.

Development began in 1999, and on August 31, 2000, Hoffman introduced CMake to the ITK community. CMake was successfully building ITK from its first day. The tool was designed around a two-stage process: first, CMake reads CMakeLists.txt files and generates platform-native build files; then the native build tool (Make, Ninja, Visual Studio, etc.) performs the actual compilation.

Growth Through Scientific Computing

CMake’s early adoption came from the scientific and high-performance computing communities. After proving itself with ITK, CMake was adopted by VTK and ParaView in 2002. Researchers at the Los Alamos, Sandia, and Livermore national laboratories became early contributors, drawn by CMake’s ability to handle large, complex codebases that needed to run on everything from desktop workstations to supercomputers.

In 2003, Ken Martin and Bill Hoffman published “Mastering CMake,” providing the first comprehensive guide to the tool. Articles in Dr. Dobb’s Journal and Linux Journal helped introduce CMake to a broader audience of developers.

Design Philosophy

Build System Generation

CMake’s fundamental design principle is that it does not build software itself – it generates build files for other tools. This separation means CMake does not need to understand every nuance of every compiler and linker. Instead, it leverages the deep platform knowledge already embedded in tools like Make, Ninja, and Visual Studio. This architectural decision allows CMake to support new platforms and toolchains without rebuilding its core logic.

System Introspection

CMake emphasizes detecting system capabilities at configure time rather than requiring developers to maintain platform-specific configuration. Commands like find_package(), check_include_file(), and try_compile() allow CMakeLists.txt files to adapt to what is actually available on the build machine. This introspection model was inspired by the approach used by autoconf, but implemented in a way that works natively on Windows and other non-Unix platforms.

Single Input, Multiple Outputs

A single set of CMakeLists.txt files can generate build files for any supported platform. A developer on macOS can generate an Xcode project while a colleague on Windows generates a Visual Studio solution, both from the same source. This eliminates the need to maintain separate build configurations per platform.

Key Features

Generator System

CMake supports multiple “generators” that produce different types of build files:

  • Makefiles: Unix Makefiles, MinGW Makefiles, NMake Makefiles
  • Ninja: High-performance build system with minimal overhead
  • IDE Projects: Visual Studio (multiple versions), Xcode, CodeBlocks, Eclipse CDT
  • Others: Watcom WMake, Borland Makefiles

Target-Based Build Model

Modern CMake (3.0+) centers on targets – logical units like executables and libraries – with associated properties. Dependencies between targets propagate automatically through visibility specifiers:

1
2
3
4
5
6
add_library(mylib src/lib.cpp)
target_include_directories(mylib PUBLIC include/)
target_compile_features(mylib PUBLIC cxx_std_17)

add_executable(myapp src/main.cpp)
target_link_libraries(myapp PRIVATE mylib)

In this model, myapp automatically inherits mylib’s public include directories and C++17 requirement. The PUBLIC, PRIVATE, and INTERFACE keywords control how properties propagate through the dependency graph.

CTest

CTest is CMake’s integrated testing framework. It discovers and runs tests defined with add_test(), supports parallel execution, timeout enforcement, and regex-based pass/fail detection. CTest can also submit results to CDash, Kitware’s testing dashboard system.

CPack

CPack generates platform-native installers and packages from CMake projects. Supported formats include DEB and RPM packages for Linux, NSIS and WiX installers for Windows, DMG bundles for macOS, and archive formats like ZIP and TGZ.

CMake Presets

Introduced in CMake 3.19, presets allow projects to define standardized configure, build, and test configurations in JSON files (CMakePresets.json). This eliminates the need to communicate long command-line invocations and ensures all developers use consistent settings.

FetchContent

The FetchContent module (CMake 3.11+) downloads and integrates external dependencies at configure time. This allows projects to declare their dependencies directly in CMakeLists.txt and have CMake retrieve and build them automatically, reducing the need for pre-installed system packages.

Generator Expressions

Generator expressions are conditional expressions evaluated at build-system generation time rather than configure time. They enable per-configuration settings and target-dependent logic:

1
2
3
target_compile_definitions(mylib
    PUBLIC $<$<CONFIG:Debug>:DEBUG_MODE>
)

Policy System

CMake maintains backward compatibility through its policy system. Each CMake version can introduce new behaviors without breaking existing projects. The cmake_minimum_required() command sets the expected policy version, and individual policies can be explicitly set to OLD or NEW behavior, allowing gradual migration.

Evolution

CMake’s evolution can be divided into two major eras:

The Classic Era (2000-2013)

Early CMake used an imperative, variable-centric approach. Build configuration involved setting global variables like CMAKE_CXX_FLAGS, INCLUDE_DIRECTORIES, and LINK_LIBRARIES. This approach worked but led to fragile builds where the order of variable settings mattered and dependencies between targets were implicit rather than explicit.

During this period, CMake steadily added platform support and features. The addition of the Ninja generator in 2012 was significant, as Ninja’s speed advantages over Make made CMake-based builds noticeably faster on large projects.

The Modern Era (2014-Present)

CMake 3.0, released in June 2014, introduced the target-based build model that defines “Modern CMake.” Instead of setting global variables, developers define properties on targets and specify how those properties propagate. This approach produces more reliable, composable, and maintainable build configurations.

Subsequent releases continued refining the modern model:

  • 3.11 (2018): FetchContent module for dependency management
  • 3.19 (2020): CMake Presets for standardized configuration
  • 3.28 (2023): C++20 module dependency scanning support

CMake 4.0, released in March 2025, marked a significant milestone by dropping backward compatibility with CMake versions older than 3.5, signaling that the modern target-based approach is now the expected standard.

Current Relevance

CMake is the dominant build system generator for C and C++ projects. Its adoption extends across virtually every segment of the C/C++ ecosystem:

  • IDEs: Visual Studio, CLion, Qt Creator, and VS Code all provide native or first-party CMake support
  • Package managers: vcpkg and Conan both integrate tightly with CMake
  • CI/CD: Major CI platforms provide CMake pre-installed in their build environments
  • Standards: CMake is the de facto standard for building C++ open-source libraries, with most expecting consumers to use find_package() for integration

The CMake community is active, with regular releases maintaining compatibility with new compilers, platforms, and language standards. The project is developed on gitlab.kitware.com and mirrored to GitHub, with contributions from both Kitware employees and the broader community.

Why It Matters

CMake’s impact on the C and C++ ecosystem has been transformative:

  1. Cross-platform C++ development: Before CMake, building a C++ project across Linux, Windows, and macOS often required maintaining separate build systems. CMake made true cross-platform development practical for projects of any size.

  2. IDE integration without lock-in: By generating native IDE project files, CMake allowed developers to use their preferred development environment without committing the project to any single IDE’s proprietary format.

  3. Ecosystem unification: CMake provided a common build interface that enabled the growth of C++ package managers and dependency management tools. The find_package() mechanism became the standard way for C++ libraries to advertise their location and usage requirements.

  4. Modern build practices: The target-based model introduced in CMake 3.0 brought software engineering principles like encapsulation and explicit dependency management to the build system layer, improving the maintainability of large C++ codebases.

  5. Scientific and industrial adoption: CMake’s origins in scientific computing and its support for complex, multi-platform builds made it the natural choice for industries where software must run reliably across diverse environments – from national laboratories to game studios to embedded systems manufacturers.

Timeline

2000
CMake first released by Kitware; originally developed for the Insight Toolkit (ITK) project funded by the U.S. National Library of Medicine
2002
CMake adopted as the build system for VTK and ParaView; gains contributors from Los Alamos, Sandia, and Livermore national laboratories
2003
'Mastering CMake' book published by Ken Martin and Bill Hoffman
2006
KDE project switches from autotools to CMake, marking a major adoption milestone for the tool
2012
Ninja build system generator added to CMake in version 2.8.8
2014
CMake 3.0 released, introducing 'Modern CMake' with target-based build model and usage requirements
2016
LLVM drops autoconf and adopts CMake as its sole build system
2017
Microsoft Visual Studio gains native CMake support, enabling direct opening of CMake projects
2020
Qt 6.0 ships with CMake as its build system, completing a transition announced in 2019
2025
CMake 4.0 released, dropping backward compatibility with versions older than 3.5

Notable Uses & Legacy

KDE

One of the largest open-source C++ projects switched its entire build system from autotools to CMake in 2006, serving as CMake's breakthrough adoption moment

LLVM/Clang

The LLVM compiler infrastructure project adopted CMake as its sole build system in 2016, replacing autoconf

Qt

The Qt cross-platform application framework adopted CMake as the build system for Qt 6, shipping in December 2020

Blender

The open-source 3D creation suite uses CMake for cross-platform builds across Linux, macOS, and Windows

MySQL

Oracle's MySQL database uses CMake as its build system for compiling across multiple platforms

Language Influence

Influenced By

Make Autotools

Running Today

Run examples using the official Docker image:

docker pull
Last updated: