Skip to main content
Introduction
"Modern CMake" course developed by Fergus Cooper and the Oxford Research Software Engineering group

"Modern CMake" course developed by Fergus Cooper and the Oxford Research Software Engineering group

Creative Commons License

Introduction

Prerequisites

This course assumes a Linux-like environment and a command line. If you are on Windows, the simplest route is the Windows Subsystem for Linux (WSL2) with an Ubuntu image, which gives you an Ubuntu shell alongside Windows. All instructions below assume a recent Ubuntu (24.04 LTS or newer) and its apt package manager. macOS works too, though you will need to translate the install commands to Homebrew.
You will also want to be comfortable enough with C++ to read and edit a small program, though the C++ in the exercises is deliberately kept simple: the interesting part is always the CMakeLists.txt.

What you need

  • CMake 3.24 or newer. The exercises use features that need a reasonably recent CMake, including header file sets, CMakePresets.json, and FetchContent's FIND_PACKAGE_ARGS.
  • A C++20 compiler, such as GCC 11 or newer, which you get from build-essential.
  • Ninja, used as the build tool in the presets we write later on.
  • Git, both to clone the exercises and because FetchContent uses it to download dependencies.
  • Eigen and Boost.Program_options, the two dependencies we ask CMake to find on the system. Boost 1.70 or newer is needed, so that it provides its own CMake config files.
Everything comes from apt:
sudo apt update sudo apt install build-essential cmake ninja-build git \ libeigen3-dev libboost-program-options-dev
Two other libraries appear later in the course, fmt and Catch2, but you do not need to install those: the build downloads them for you. That does mean you need a working internet connection when you reach those sections.

Checking your setup

cmake --version g++ --version ninja --version
Older Ubuntu releases ship a CMake that is too old for this course. Ubuntu 22.04, for instance, packages CMake 3.22, which predates the header file sets we rely on when installing a library.
If cmake --version reports anything below 3.24, upgrade rather than working around it. Kitware, who develop CMake, publish an APT repository with current releases, and pip install cmake or snap install cmake --classic are quick alternatives.

Course materials

Clone the material repository and change your current working directory to the project root:
git clone https://github.com/OxfordRSE/ModernCMakeCourse cd ModernCMakeCourse

What is CMake and why should I use it?

To compile a simple C++ project, you might compile the source files on the command line by directly invoking the compiler:
g++ -std=c++20 main.cpp functionality.cpp -o main_executable -I/usr/local/include/eigen3 -lboost_program_options
This is fine for small projects, but it quickly becomes unwieldy as the number of source files and dependencies increases. Moreover, it is not portable: the above command will only work on systems with the Boost and Eigen libraries installed in the specified locations. We might also have to change the compiler, and would have to change the command line invocation.
Another option is to use a build tool like Make, which allows us to specify the build process by defining rules. This can scale to larger projects, but still is not completely portable as the rules are specific to Make, and we still have to manually specify the compiler and libraries.
CMake is a build system generator that allows us to specify the build process for large project, in a portable way, and to generate build files for a variety of build tools like Unix Makefiles, Visual Studio projects, or the Ninja build tool. It has a lot of features for finding dependencies and for making the build process more portable across operating systems, compilers, and architectures. It has many features, but we will only cover the basics here.

Enter CMake

In CMake you describe targets (what to build), inputs (the sources files), and configuration (what libraries to use, what compiler settings, etc.).
From that description, CMake generates the rules for a build tool of your choosing: a Makefile, a Ninja build file, an IDE project, or something else. CMake doesn't build your project itself, and you don't write the rules by hand.
CMake works on Linux, Windows, macOS and more.