How to Build CMake Projects¶
CMake is a meta-buildsystem, meaning it generates buildsystem files from its standardized, cross-platform scripting language. With this comes additional features, like generating compilation databases, invoking custom commands, and installing projects.
This document describes how to use the cmake command line program to configure and build a CMake-based project. For an introduction to creating CMake-based projects with their scripting language, see Kitware’s CMake Tutorial.
TL;DR¶
cmake -B <build-dir> -G Ninja -DCMAKE_BUILD_TYPE=Release # configure
cmake --build <build-dir> # build
ctest --test-dir <build-dir> --output-on-failure # test
cmake --install <build-dir> # install
Installing CMake¶
Install cmake with your system’s package manager:
sudo pacman -S cmake # Arch
sudo apt install cmake # Debian
brew install cmake # MacOS
CMake can be also downloaded from Kitware’s official download page.
Getting Started¶
For the following commands, <build-dir> is the directory where you would like CMake to generate the native buildsystem and place its artifacts. Common names are build, build-debug, or build-release. Separate build directories can be simultaneously used to facilitate multiple builds of a project. There are certain buildsystems, such as Xcode and Visual Studio, that support multiple build configurations within a single build directory.
All of the following commands should be invoked from the project directory containing its top-level CMakeLists.txt file, which is widely the project’s root directory.
Configuring¶
“Configuring” a project is the step where CMake will perform system introspection, interpret the CMake scripts, and generate native build-system files. It’s required before building a project or performing any subsequent cmake steps.
Most simply, just the build directory can be specified, and the source directory will be implied as the current directory.
cmake -B <build-dir>
Commonly, the buildsystem
generator, what generates the
native build-system files, will be specified using -G
.
cmake -B <build-dir> -G Ninja
cmake -B <build-dir> -G "Unix Makefiles"
cmake -B <build-dir> -G Xcode
cmake -B <build-dir> -G "Visual Studio 17 2022"
CMake variable definitions can be specified on the command line with -D
, which will override
or introduce CMake cache variables before CMake interprets the list files (CMakeLists.txt).
Command-line definitions are used to change CMake’s behaviour or to control custom features
of a project, since the project’s list files will have access to their definitions. These cache
variables are preserved between CMake invocations, and are stored in the file
<build-dir>/CMakeCache.txt, as opposed to normal variables, which are internal to the CMake
scripts (set()).
cmake -B <build-dir> -G Ninja -D CMAKE_BUILD_TYPE=Release
cmake -B <build-dir> -G Ninja -D BUILD_SHARED_LIBS=ON
Building¶
Building executes the native buildsystem. Although the native buildsystem command-line programs can be used for this (make, ninja, etc.), cmake can be used to do this in a cross-platform, buildsystem agnostic manner.
All default build targets from configuring can be built with:
cmake --build <build-dir>
Specific targets can be individually built using the flag target
:
cmake --build <build-dir> --target <target>
# Ex. cmake --build build-release --target json-parser
For multi-configuration generators (Ninja Multi-Config, MSVC), those that correspond to
build-systems which support multiple build-types in a single build-directory, add the
--config
flag to build commands:
cmake --build <build-dir> --config <config>
# Ex. cmake --build build --config Release
Note
All of the available targets can be listed with cmake --build <build-dir> --target help
Deleting build artifacts from a build directory, also known as cleaning, is useful to subsequently
build without relying on any previous artifacts. CMake always generates a clean target that can be
“built” to explicitly clean, or the --clean-first
flag can be provided with --build
,
to clean and build in one step:
cmake --build <build-dir> --target clean # only clean
cmake --build <build-dir> --clean-first # clean, then build
Installing¶
By default, installing will install the build artifacts in <build-dir> to your system folders,
therefore requiring administrator permissions. The installation prefix depends on your system - for
Unix, the default is /usr/local. JCM’s jcm_setup_project()
changes the default to
/opt/<project> to align better with FHS, but particular projects can
override this default.
cmake --install <build-dir>
The installation prefix can easily be changed with the --prefix
flag:
cmake --install <build-dir> --prefix <install-prefix>
# Ex. cmake --install build-release --prefix ./install
# Ex. cmake --install build-release --prefix /opt/my-project
It’s favourable to strip the binaries before installing with the --strip
flag. This will
remove any debug symbols or unneeded dynamic library links.
cmake --install build-release --strip
# Ex. cmake --install build-release --strip --prefix ./install
Like the build step, on multi-configuration generators (Ninja Multi-Config, MSVC), add the
--config
option to install commands. When unspecified, CMake will choose the first
configuration your buildsystem supports, which may or may not be the configuration built above:
cmake --install <build-dir> --config <config>
# Ex. cmake --install build --config Release
The installation can be limited to a specific subsection of a project’s installation, called an
install component, using the --component
option. Install components are often used to
separate installed artifacts by their release and development artifacts, or by license variants.
Additionally, an install component may not necessarily be installed by default (above), consequently
requiring explicit component-specific installation.
cmake --install <build-dir> --component <component>
# Ex. cmake --install build --component libimage_Release
# Ex. cmake --install build --component libimage_free
Uninstalling¶
If a custom installation prefix was chosen, you can simply remove the entire installation directory.
Upon installing, CMake will generate a file <build-dir>/install_manifest.txt listing all installed files. Removing these files and any generated parent directories will uninstall the project.
Testing¶
Testing is done with a tool called CTest. In a project’s list files, they can register tests with CTest, then these tests will be invoked when ctest is invoked, and their outcomes will be recorded and summarized by CTest.
Although CTest is a powerful tool which supports publishing to dashboards, test scripts, test parallelization, and even building entire CMake projects, basic examples to test an existing project are shown below - these options can be joined:
ctest --test-dir <build-dir> # run all tests, and show summary at the end
ctest --test-dir <build-dir> --output-on-failure # print output from failed tests
ctest --test-dir <build-dir> --stop-on-failure # stop all testing when a single failure occurs
ctest --test-dir <build-dir> --rerun-failed # only run tests that did not previously pass
ctest --test-dir <build-dir> -R <regex> # run all tests matching <regex>
ctest --test-dir <build-dir> -E <regex> # exclude all tests matching <regex>
ctest --test-dir --output-junit <file> # produce junit formatted test summary in <file>
ctest --test-dir --build-config <cfg> # Desired config for Multi-Config generators
Projects often require you to enable building tests in the configuration stage through a variable, as they’re off by default.
cmake -B <build-dir> -D <enable-test-var>:BOOL=ON
# Ex. cmake -B <build-dir> -D BUILD_TESTING:BOOL=ON
CMake Presets¶
CMake presets exist in the files CMakePresets.json and CMakeUserPresets.json. The former is checked into version control, while the latter is for personal use. These include JSON descriptions of settings for cmake (and ctest), which can be invoked by simply naming the desired preset.
cmake --preset <configure-preset> # configure using preset
cmake --build --preset <build-preset> # build using preset
ctest --preset <test-preset> # test using preset
For example, if a project’s CMakePresets.json named a config preset called debug-tests, and build preset called unit-tests, and a test preset called core-tests, a user’s workflow could be simplified to the following commands, instead of manually providing numerous command-line options.
cmake --preset debug-tests # configure using preset
cmake --build --preset unit-tests # build using preset
ctest --preset core-tests # test using preset