CMake Cookbook

4.4 (18 reviews total)
By Radovan Bast , Roberto Di Remigio
    Advance your knowledge in tech with a Packt subscription

  • Instant online access to over 7,500+ books and videos
  • Constantly updated with 100+ new titles each month
  • Breadth and depth in over 1,000+ technologies
  1. Setting up Your System

About this book

CMake is cross-platform, open-source software for managing the build process in a portable fashion. This book features a collection of recipes and building blocks with tips and techniques for working with CMake, CTest, CPack, and CDash.

CMake Cookbook includes real-world examples in the form of recipes that cover different ways to structure, configure, build, and test small- to large-scale code projects. You will learn to use CMake's command-line tools and master modern CMake practices for configuring, building, and testing binaries and libraries. With this book, you will be able to work with external libraries and structure your own projects in a modular and reusable way. You will be well-equipped to generate native build scripts for Linux, MacOS, and Windows, simplify and refactor projects using CMake, and port projects to CMake.

Publication date:
September 2018


Setting up Your System

Before diving into CMake and the recipes in this book, you will need to set your system up to successfully run all of the examples. In this section, we will discuss the following topics:

  1. How to obtain the code for the recipes
  2. How to install all of the tools required to run the code samples on GNU/Linux, macOS, and Windows
  3. How the automated testing for the repository works
  4. How to report problems with the recipes and suggest improvements

We have strived to make our discussions of the topics in this book as accessible to novices as possible. However, this book does not start from absolute scratch. We assume that you have basic knowledge of the native tools for building software that are available on your platform of choice. It is also helpful (but not required) to have basic experience with version control using Git, to interact with the repository holding the recipe sources.


Obtaining the code

The source code for the recipes in this book is available on GitHub, at The code is licensed under the standard open source MIT license: this is a permissive software license, and you can reuse and remix the code in whatever way you see fit, as long as the original copyright and license notice are included in any copies of the software/source. The full text of the license is available at

In order to test the recipes by yourself, you will need a working installation of Git, obtained as follows:

  • All major GNU/Linux distributions offer Git prepackaged, via their package managers. If that is not your case, a binary distribution can be downloaded from the Git project website at
  • On macOS, it is possible to use Homebrew or MacPorts to install Git.
  • On Windows, you can download the Git executable from the Git project website at

Alternatively, you can access the examples with the GitHub desktop client at

Yet another alternative is to download and extract the ZIP file from

Once you have Git installed, you can clone the repository to your local machine, as follows:

$ git clone

This will create a folder named cmake-cookbook. The book and the repository are organized in chapters and recipes. The numbering of chapters and the order of recipes in the repository reflect the order in the text. Each recipe is further organized into example folders. Some of the recipes have more than one example, usually when similar CMake concepts are illustrated in different programming languages.

The recipes are tested on GNU/Linux, macOS, and Windows, using state-of-the-art continuous integration services. We will discuss the testing set up shortly.

We have tagged the precise versions that correspond to the examples printed in this book with the tag v1.0. For maximum overlap with the book text, you can fetch this particular version as follows:

$ git clone --single-branch -b v1.0

We expect to receive bug fixes and the GitHub repository to evolve. To get the latest updates, you may prefer to follow the master branch of the repository, instead.


Docker image

You will likely find that the easiest approach to testing the book's recipes in a software environment (which contains all of the dependencies preinstalled) is to use a Docker image that we have set up, based on Ubuntu 18.04. You can install Docker on your favorite operating system, following the official documentation at

Once Docker is installed, you can run our image and test the recipes with the full software environment in place, as follows:

$ docker run -it devcafe/cmake-cookbook_ubuntu-18.04
$ git clone
$ cd cmake-cookbook
$ pipenv install --three
$ pipenv run python testing/ 'chapter-*/recipe-*'

Installing prerequisite software

An alternative to running the book recipes in a container is to install the dependencies directly on the host operating system. For this, we have assembled a minimal toolstack that can be used as a basic starting point for all of our recipes. You will have to install the following:

  1. CMake
  2. Language-specific tools, that is, the compilers
  3. Build automation tools
  4. Python

We will also detail how to install the additional dependencies required by some of the recipes.

Getting CMake

CMake 3.5 is the minimum required version of CMake for this book. Only a few, specific recipes and examples that demonstrate useful features that were introduced after version 3.5 will require a more recent version of CMake. The introduction to every recipe features an info box, pointing out where the code is available, which examples are given, and the minimum version of CMake required. The info boxes will look like the following box:

The code for this recipe is available at, and includes a C example. The recipe is valid with CMake version 3.5 (and higher) and has been tested on GNU/Linux, macOS, and Windows.

Some, if not most, of the recipes will still be valid with older versions of CMake. However, we have made no attempts to test this assumption, since we consider CMake 3.5 to be the default on most systems and distributions. We also consider upgrading to later versions of CMake to be a straightforward step.

CMake can be installed in a number of different ways. Downloading and extracting the binary distribution maintained by Kitware will work across all platforms. The download page is at

Most GNU/Linux distributions have CMake available in their package managers. However, on some distributions, the packaged version can be rather old, so downloading the binary maintained by Kitware is still the preferred option. The following commands will download and install CMake 3.5.2 under $HOME/Deps/cmake (adjust this path to your preference), from the version packaged by CMake:

$ cmake_version="3.5.2"
$ target_path=$HOME/Deps/cmake/${cmake_version}
$ cmake_url="${cmake_version%.*}/cmake-${cmake_version}-Linux-x86_64.tar.gz"
$ mkdir -p "${target_path}"
$ curl -Ls "${cmake_url}" | tar -xz -C "${target_path}" --strip-components=1
$ export PATH=$HOME/Deps/cmake/${cmake_version}/bin${PATH:+:$PATH}
$ cmake --version

Homebrew for macOS reliably ships the latest version of CMake:

$ brew upgrade cmake

On Windows, you can use Visual Studio 2017, which provides CMake support. The installation of Visual Studio 2017 is documented in Chapter 13, Alternative Generators and Cross-compilation, Recipe 1, Building a CMake project using Visual Studio 2017.

Alternatively, you can download the MSYS2 installer from , follow the instructions given therein to update the list of packages, and then install CMake using the package manager, pacman. The following code assumes that we are building the 64-bit version:

$ pacman -S mingw64/mingw-w64-x86_64-cmake

For the 32-bit version, use the following (though we will only refer to 64-bit versions in future, for the sake of brevity):

$ pacman -S mingw64/mingw-w64-i686-cmake

Another nice feature of MSYS2 is that it provides a terminal on Windows that feels and behaves like a terminal on a Unix-like operating system, providing a useful development environment.


We will need compilers for C++, C, and Fortran. These should be fairly recent, as we require support for recent language standards in most of the recipes. CMake offers very good support for many compilers, from both commercial and non-commercial vendors. To keep the recipes consistently cross-platform and as operating system independent as possible, we have worked with open source compilers:

  • On GNU/Linux, the GNU Compiler Collection (GCC) is the obvious choice. It is free and available for all distributions. For example, on Ubuntu, you can install the compilers as follows:
$ sudo apt-get install g++ gcc gfortran 
  • Clang, in the LLVM family, is also a good choice for C++ and C:
$ sudo apt-get install clang clang++ gfortran
  • On macOS, the LLVM compilers shipped with XCode will work for C++ and C. We have used the Fortran compiler from GCC in our macOS testing. This has to be installed separately, using the package manager. For example, the command for Homebrew is as follows:
$ brew install gcc
  • On Windows, you can use Visual Studio for the C++ and C recipes. Alternatively, you can use the MSYS2 installer and install the entire toolchain, including a C++, C, and Fortran compiler, with the following single command in an MSYS2 environment (for the 64-bit version):
$ pacman -S mingw64/mingw-w64-x86_64-toolchain

Build-automation tools

These build-automation tools will provide the infrastructure for building and linking the projects presented in the recipes. What you will end up installing and using strongly depends on your operating system and your taste:

  • On GNU/Linux, GNU Make will most likely be installed automatically, when installing the compilers.
  • On macOS, XCode will provide GNU Make.
  • On Windows, Visual Studio will provide you with the complete infrastructure. In the MSYS2 environment, GNU Make is installed as a part of the mingw64/mingw-w64-x86_64-toolchain package, which we installed previously.

For maximum portability, we have made the recipes as agnostic about these system-dependent details as possible. A clear advantage of this approach is that configuring, building, and linking are native to each platform and each set of compilers.

The Ninja program is a different build-automation tool that works on GNU/Linux, macOS, and Windows. Ninja is a new build tool, with a focus on speed, especially for incremental rebuilds. Prepackaged binaries for GNU/Linux, macOS, and Windows can be found on the project's GitHub repository at

Using CMake and Ninja with Fortran projects requires some care. CMake 3.7.2 or later is required, along with the version of Ninja maintained by Kitware, available at

On GNU/Linux, you can install Ninja with the following series of commands:

$ mkdir -p ninja
$ ninja_url=""
$ curl -Ls ${ninja_url} | tar -xz -C ninja --strip-components=1
$ export PATH=$HOME/Deps/ninja${PATH:+:$PATH}

On Windows, using the MSYS2 environment (assuming the 64-bit version), executing the command:

$ pacman -S mingw64/mingw-w64-x86_64-ninja
We recommend reading the essay at for an enlightening discussion of Ninja's history and design choices.


This book is about CMake, but some of the recipes, along with the whole infrastructure powering testing, need Python. Thus, first and foremost, you will need a working installation of Python: the interpreter, header files, and libraries. The end of life for Python 2.7 was announced for 2020, and we will thus use Python 3.5.

On Ubuntu 14.04 LTS (this is the environment used by Travis CI which we will discuss later on), Python 3.5 can be installed as follows:

$ sudo apt-get install python3.5-dev

On Windows, using the MSYS2 environment, the Python environment can be installed as follows (assuming the 64-bit version):

$ pacman -S mingw64/mingw-w64-x86_64-python3
$ pacman -S mingw64/mingw-w64-x86_64-python3-pip
$ python3 -m pip install pipenv

Specific Python modules are also required, in order to run the testing machinery that we have put in place. These can be installed system-wide by using your favorite package manager, or in an isolated environment. The latter approach is highly recommended, as it offers the following advantages:

  • You can install packages and clean up installations without affecting the system environment.
  • Packages can be installed without administrator privileges.
  • You lower the risk of version and dependency clashes.
  • You gain much better control over package dependencies, for reproducibility.

We have prepared a Pipfile for this purpose. In combination with its Pipfile.lock, you can use Pipenv ( to generate an isolated environment, with all packages installed. To create this environment for the recipe example repository, run the following commands in the top-level directory of the repository:

$ pip install --user pip pipenv --upgrade
$ pipenv install --python python3.5

The pipenv shell command will drop you into a command-line environment with the specific version of Python and all of the packages available. Executing exit will bring you back to a clean environment. You can also use pipenv run to directly execute a command within the isolated environment.

Alternatively, the requirements.txt file in the repository can be used, in combination with Virtualenv ( and pip, to achieve the same effect:

$ virtualenv --python=python3.5 venv
$ source venv/bin/activate
$ pip install -r requirements.txt

The virtual environment can be exited by using the deactivate command.

Yet another alternative is to use Conda environments. To do so, we suggest installing Miniconda. The following instructions will install the latest Miniconda to the directory $HOME/Deps/conda, for GNU/Linux (download from or macOS (download from

$ curl -Ls >
$ bash -b -p "$HOME"/Deps/conda &> /dev/null
$ touch "$HOME"/Deps/conda/conda-meta/pinned
$ export PATH=$HOME/Deps/conda/bin${PATH:+:$PATH}
$ conda config --set show_channel_urls True
$ conda config --set changeps1 no
$ conda update --all
$ conda clean -tipy

On Windows, you can download the latest Miniconda from The package can be installed using PowerShell, as follows:

$basedir = $pwd.Path + "\"
$filepath = $basedir + "Miniconda3-latest-Windows-x86_64.exe"
$Anaconda_loc = "C:\Deps\conda"
$args = "/InstallationType=JustMe /AddToPath=0 /RegisterPython=0 /S /D=$Anaconda_loc"
Start-Process -FilePath $filepath -ArgumentList $args -Wait -Passthru

$conda_path = $Anaconda_loc + "\Scripts\conda.exe"
$args = "config --set show_channel_urls True"
Start-Process -FilePath "$conda_path" -ArgumentList $args -Wait -Passthru
$args = "config --set changeps1 no"
Start-Process -FilePath "$conda_path" -ArgumentList $args -Wait -Passthru
$args = "update --all"
Start-Process -FilePath "$conda_path" -ArgumentList $args -Wait -Passthru
$args = "clean -tipy"
Start-Process -FilePath "$conda_path" -ArgumentList $args -Wait -Passthru

Once Conda is installed, the Python modules can be installed as follows:

$ conda create -n cmake-cookbook python=3.5
$ conda activate cmake-cookbook
$ conda install --file requirements.txt

Executing conda deactivate will drop you outside of the isolated environment.

Additional software

Some recipes will require additional software, which will be covered in the following sections.


Most Linux distributions provide packages for BLAS and LAPACK. For example, on Ubuntu 14.04 LTS, you can run the following:

$ sudo apt-get install libatlas-dev liblapack-dev liblapacke-dev

On macOS, the Accelerate libraries, shipped with XCode, are enough for our purposes.

On Windows, using the MSYS2 environment, these libraries can be installed as follows (assuming the 64-bit version):

$ pacman -S mingw64/mingw-w64-x86_64-openblas

Alternatively, you can download the reference implementation of BLAS and LAPACK from GitHub ( and compile the libraries from sources. Commercial vendors might offer packages for their own implementations of the BLAS and LAPACK APIs, available as installers for your platform.

Message passing interface (MPI)

There are many commercial and non-commercial implementations of MPI. For our introductory purposes, it is enough to install any of the freely available non-commercial implementations. On Ubuntu 14.04 LTS, we recommend OpenMPI. It can be installed with the following command:

$ sudo apt-get install openmpi-bin libopenmpi-dev

For macOS, Homebrew distributes MPICH:

$ brew install mpich

It is also possible to compile OpenMPI from the sources publicly available at

For Windows, the Microsoft MPI implementation can be installed via

The Eigen linear algebra template library

Some recipes will need the Eigen linear algebra template library, version 3.3 or later. If your package manager does not provide Eigen, you can install it from the online source archive ( For example, on GNU/Linux and macOS, you can install Eigen to the directory $HOME/Deps/eigen, as follows:

$ eigen_version="3.3.4"
$ mkdir -p eigen
$ curl -Ls${eigen_version}.tar.gz | tar -xz -C eigen --strip-components=1
$ cd eigen
$ cmake -H. -Bbuild_eigen -DCMAKE_INSTALL_PREFIX="$HOME/Deps/eigen" &> /dev/null
$ cmake --build build_eigen -- install &> /dev/null

The Boost libraries

Boost packages are available for every operating system; most Linux distributions have packages available through their package managers. On Ubuntu 14.04 LTS, for instance, the Boost Filesystem, Boost Python, and Boost Test libraries can be installed with the following command:

$ sudo apt-get install libboost-filesystem-dev libboost-python-dev libboost-test-dev

For macOS, both MacPorts and Homebrew provide packages for recent versions of Boost. Our testing setup on macOS installs Boost as follows:

$ brew cask uninstall --force oclint
$ brew uninstall --force --ignore-dependencies boost
$ brew install boost
$ brew install boost-python3

Prebuilt binary distributions for Windows are also available for download from the Boost website at Alternatively, you can download the sources from and compile the libraries yourself.


On Debian/Ubuntu-like systems, cross-compilers can be installed with the following command:

$ sudo apt-get install gcc-mingw-w64 g++-mingw-w64 gfortran-mingw-w64

On macOS, using Brew, the cross-compilers can be installed as follows:

$ brew install mingw-w64

Other package managers offer corresponding packages.

An alternative to using packaged cross-compilers is to build them from sources, using the M cross environment (

ZeroMQ, pkg-config, UUID, and Doxygen

On Ubuntu 14.04 LTS, these packages can be installed as follows:

$ sudo apt-get install pkg-config libzmq3-dev doxygen graphviz-dev uuid-dev

On macOS, we recommend installing with Brew:

$ brew install ossp-uuid pkg-config zeromq doxygen

The pkg-config program and UUID library are only available on Unix-like systems.

On Windows, using the MSYS2 environment, these dependencies can be installed as follows (assuming the 64-bit version):

$ pacman -S mingw64/mingw-w64-x86_64-zeromq
$ pacman -S mingw64/mingw-w64-x86_64-pkg-config
$ pacman -S mingw64/mingw-w64-x86_64-doxygen
$ pacman -S mingw64/mingw-w64-x86_64-graphviz

Conda build and deployment tools

The recipes exploring packaging with Conda will need Miniconda and the Conda build and deployment tools installed on the system. The instructions for the installation of Miniconda were given previously. To install Conda build and deployment tools on GNU/Linux and macOS, run the following commands:

$ conda install --yes --quiet conda-build anaconda-client jinja2 setuptools
$ conda clean -tipsy
$ conda info -a

These tools can be installed on Windows as follows:

$conda_path = "C:\Deps\conda\Scripts\conda.exe"

$args = "install --yes --quiet conda-build anaconda-client jinja2 setuptools"
Start-Process -FilePath "$conda_path" -ArgumentList $args -Wait -Passthru

$args = "clean -tipsy"
Start-Process -FilePath "$conda_path" -ArgumentList $args -Wait -Passthru

$args = "info -a"
Start-Process -FilePath "$conda_path" -ArgumentList $args -Wait -Passthru

Testing the recipes

The recipes are tested on state-of-the-art continuous integration (CI) services: Travis ( for GNU/Linux and macOS, Appveyor ( for Windows, and CircleCI ( for additional GNU/Linux testing with commercial compilers. The configuration files for the CI services can be found in the repository ( .travis.yml for Travis, .appveyor.yml for Appveyor, and .circleci/config.yml for CircleCI. Additional installation scripts for Travis and Appveyor can be found in the folder testing/dependencies.

We test the recipes with CMake 3.5.2 and CMake 3.12.1 on the Travis GNU/Linux infrastructure. CMake 3.12.1 is used on the Travis macOS infrastructure. On Appveyor, testing uses CMake 3.11.3. On Circle, CMake 3.12.1 is used.

The testing machinery is a set of Python scripts that are also contained in the testing folder. The script will run tests and report their statuses. Recipes can be tested in isolation, or in batches; accepts a regular expression as command-line input, for example:

$ pipenv run python testing/ 'chapter-0[1,7]/recipe-0[1,2,5]'

This command will run tests for Recipes 1, 2, and 5, in Chapters 1 and 7. A sample of the output looks as follows:

To get more verbose output, set VERBOSE_OUTPUT=ON:

$ env VERBOSE_OUTPUT=ON pipenv run python testing/ 'chapter-*/recipe-*'

Reporting problems and suggesting improvements

About the Authors

  • Radovan Bast

    Radovan is working at the High Performance Computing Group at UiT - The Arctic University of Norway in Troms and leads the CodeRefinery project. He has a PhD in theoretical chemistry and as code developer is contributing to a number of quantum chemistry programs. He enjoys learning new programming languages and techniques, and to teach programming to students and researchers. He got in touch with CMake in 2008 and has ported a number of research codes and migrated a number of communities to CMake since.

    Browse publications by this author
  • Roberto Di Remigio

    Roberto is a postdoctoral fellow in theoretical chemistry at the UiT - The Arctic University of Norway in Troms, Norway and Virginia Tech, USA. He is currently working on stochastic methods and solvation models. He is a developer of the PCMSolver library and the Psi4 open source quantum chemistry program. He contributes or has contributed to the development of popular quantum chemistry codes and libraries: DIRAC, MRCPP, DALTON, LSDALTON, XCFun, and ReSpect. He usually programs in C++ and Fortran.

    Browse publications by this author

Latest Reviews

(18 reviews total)
Excellent resource if you are new to CMake
Tells me everything I wanted to know and more!
ı never I could find a good source on Cmake...this book is awsome just buy there is everything you need..even more

Recommended For You

Book Title
Unlock this book and the full library for FREE
Start free trial