Quick Introduction to CMake

This chapter is geared towards users who have not used CMake before. If you have used CMake previously feel free to skip this chapter.

About CMake

Let’s start with some basic background on CMake.

What is CMake?

CMake stands for “Cross platform Make” and is a tool to facilitate building packages on a variety of platforms. The CMake suite of programs contains a number of programs, but for our present purposes the only one you need to be aware of is the literal CMake program, cmake.

Obtaining CMake

CMake’s official website is here and contains links to download and install the CMake package. CMake is also readily available in most package managers. Most modern packages that rely on CMake require at least CMake version 3.0, but you’ll need at least version 3.14 to build CMaize-based projects.

Building CMake

For now follow CMake’s instructions as I’m too lazy to write my own.

Using CMake

Basic CMake Usage

Now that you have the CMake package installed on your system you can run the cmake command. Let’s say you just downloaded some package an_awesome_package. If you look at the file structure of an_awesome_package you should see one or more files called CMakeLists.txt. These files are written by the package maintainer and tell CMake how to build the package. Conventional usage will have you run the cmake command in the directory that contains an_awesome_package’s top-level CMakeLists.txt (and this tutorial assumes that this is the case). Thus in that directory you minimally will need to run:

cmake -H. -B<scratch_dir>

The -H. tells CMake to start running in the current directory. It is possible to run CMake from another directory and adjust the path to -H, but unless the package maintainer is a CMake guru (or used CMaize) doing so is likely to break the build; hence, it is good practice to always run in the same directory as the top-level CMakeLists.txt and just consider the -H. as boilerplate.

The -B<scratch_dir> tells CMake where it can put autogenerated files as well as any intermediate object files. You should replace <scratch_dir> with a descriptive name such as build-debug to signal that this is the build directory for a debug build (assuming of course that you are building a debug version of the package).

After running the cmake command a plethora of text output usually ensues ending with something like:

-- Configuring done
-- Generating done
-- Build files have been written to: /path/to/the/build/directory/you/set

[Finished]

This signals that the cmake command has run successfully. It has not built your project yet, rather it has generated the files required to build the project. That said, typically you are home free once the cmake command has completed.

Realistic Usage

The usage in the previous section is somewhat idealized. Generally speaking you will need to provide more information. CMake defines a lot of options and we have collected them for you on the CMake Option Variables page. Two of the more important options you should be aware of are CMAKE_INSTALL_PREFIX and CMAKE_PREFIX_PATH. While they may sound similar they are used for two different purposes. CMAKE_INSTALL_PREFIX tells CMake where to install the package after it is built. On Unix-like machines, it defaults to something like /usr/local resulting in executables being installed to /usr/local/bin, header files to /usr/local/include, etc. CMAKE_PREFIX_PATH tells CMake where to look for dependencies.

Now that you know about options, how do we set them? The answer is like this:

cmake -H. -B<scratch_dir> -DOPTION1=VALUE1 -DOPTION2=VALUE2...

That is to say they are appended to the cmake command in the format -D<option>=<value>. Say we wanted to install the package to /foo/bar the command to do this is:

cmake -H. -B<scratch_dir> -DCMAKE_INSTALL_PREFIX=/foo/bar

Some CMake variables, like CMAKE_PREFIX_PATH, take lists. Lists are passed to CMake by placing the contents in double quotes and separating items with semicolons. For example, to tell CMake to look in /foo and /bar for dependencies the command is:

cmake -H. -B<scratch_dir> -DCMAKE_PREFIX_PATH="/foo;/bar"

It is important to note that packages may also define their own options, in addition to those provided by CMake. Hence you should consult the package’s build documentation for any package specific options that are available.

Building and Installing

With the package configured, all that remains is to actually build it and to install it. The commands to do this are similar and both are executed in the same directory as the top-level CMakeLists.txt. Building is done by:

cmake --build <scratch_dir>

and installing is done by:

cmake --build <scratch_dir> --target install

The install command may need to be run with administrator privileges if the current user does not have sufficient permissions to write to the installation destination.