Getting Started With CMake         Introduction to CMake - the Ogre build system
Image

This section introduces you to CMake and explains the concepts as well as how you can get and use CMake.

Quick Start For The Impatient

If you don't care to read about the hows or whys of CMake for now and just want to build OGRE, go to the CMake Quick Start Guide. It's worth coming back here later to read the rest though!

About CMake

CMake is a cross-platform build system. Any project wanting to use CMake describes its build process in simple text files via special CMake commands. CMake is then invoked on the project's source directory, parses these text files and generates a native build chain for the desired platform and compiler. CMake also provides options to the user with which the build process can be customised.

If you have built software on Linux, you are very likely familiar with the

./configure && make && make install

way of building software. To get a first expression of what CMake does, imagine it to be a replacement for 'configure'. CMake now takes the part of finding all required dependency libraries and customising build options - but instead of having to supply command line options to configure, you can comfortably choose them with a GUI provided by CMake. Once you're done CMake generates a set of Makefiles for you, and you compile and install the software with make as before.

On Windows and Visual Studio there is usually no configuration step. Projects usually provide a Visual Studio solution file which you open and use to compile the software. VS solutions, however, provide little help in configuring a build. There is no easy way to switch between threaded and non-threaded Ogre builds, for example. Additionally, include directories and linked libraries of dependencies are pretty much fixed, and if your directory layout differs significantly from the creator's, you may have to painfully edit the settings of every project in the solution file manually to reflect your personal setup. CMake adds the missing configuration step: A project no longer ships VS solution files, instead any user generates a custom VS solution via CMake. CMake will find all the necessary dependencies and give you the option to customise the build in any way the developers support. Once you're done with CMake, you will be left with a Visual Studio solution file just as before which is then used to compile the project.

Getting and installing CMake

You can download CMake at the official website at www.cmake.org. In the navigation bar of the site go to "Resources -> Download". Pre-built binary packages are available for many platforms, but you can also decide to compile CMake from source.

Binary packages

Windows

You can choose to download CMake as either an executable installer or as a ZIP archive. Choose whatever you prefer. The installer will setup some links in your start menu to the CMake GUI.

Linux

Chances are good your distribution already offers packages for CMake. Search for cmake in your package manager (apt, yum or whatever your distribution uses). Some distributions, like Ubuntu starting from version 8.10, also have a package cmake-gui. Install that as well. On Ubuntu, the following typed in a console will install cmake:

sudo apt-get install cmake cmake-gui


Alternatively the CMake website offers generic Linux binaries. There is a compressed archive (.tar.gz) which you can extract, but there's also an installer version (.sh). Download the installer, open a console and switch to the download directory. Then you can install CMake with the following command (adjust the filename to the one you actually downloaded):

sh cmake-2.6.3-Linux-i386.sh --prefix=/usr/local --exclude-subdir


Of course, you can exchange /usr/local to any directory you want to install CMake to. However, that directory must exist before you run the install command.

Mac OSX

CMake is available as a universal binary for Mac OSX Tiger and later. It is packaged in three ways, as a .dmg, a .tar.gz, and a .tar.Z. Download any of these files. The .dmg comes with an automated installer. During the installation it will ask you if you want it to install itself for command line usage. Both the .tar.gz and the .tar.Z come with CMake as an application, install just like you install any other application - drag and drop to "Applications". When you first run CMake, it will prompt you to install itself for command line usage (You can later access this option from the "Tools" menu).

Building CMake from source

If you want or need to, you can also download a source archive of the CMake site, or get the current development version from cvs (see: CMake CVS). Now, if you are on Windows and using Visual Studio, there's a slight twist: You need CMake in order to build CMake! So refer to the above section and download a binary release of CMake first. Otherwise, you can use the provided autotools build. In a console, run

./configure && make && make install

to build and install CMake. Building CMake with CMake is done like any other project building with CMake; refer to the sections below to learn how CMake works and how to use it.

CMake basics

First of all you need to learn some basic concepts of how CMake works. This may be a bit dull, but it should ease your understanding of a CMake-based build process.

Generators

Like any other build system CMake is told the names of the target to build, their type (executable, library, test, ...) and the source files which belong to a particular target. The way to compile sources and build targets depends on the compiler and platform used, and CMake abstracts this with the help of its generators.

In a manner of speaking a generator "translates" the platform-agnostic input CMake gets and produces a platform-dependent build system you can then use to compile the project. For example, on Windows there are CMake generators for both Visual Studio 2005/2008 versions which can either create solution files for the Visual Studio IDE or Makefiles for nmake. For GCC-based builds there exist several generators for MinGW and Unix platforms which produce Makefiles. There are also generators which produce wrappers for Code::Blocks and Eclipse around these Makefiles.

The point to remember here is that CMake doesn't control the build of a project directly, instead it uses a generator of your choice to create a native build system for your compiler and platform which fulfills the job.

Build options and the CMake cache

As already mentioned CMake goes beyond the simple setup of build targets. CMake can find dependencies, do conditional builds and even set different compile or link flags depending on the choice of desired options by the user. To do this CMake presents the user with a couple of adjustable options. These options are presented in the form of variables which usually are of the form PACKAGE_SOME_OPTION and may contain anything from boolean switches to numbers and strings. The user can modify these variables which are stored by CMake in a special cache. The contents of these cache variables and their effect on the build process are taken into account before the chosen generator creates the native build system.

Directories

During a build with CMake there are three different directories involved: The source dir, the build dir and the install dir.

Source directory

The source dir is where, obviously, the project's sources are stored. This is the directory to which you extracted the project's source archive or to where you checked out the sources from a version control system. The source dir also contains the files which describe the build to CMake. Mostly these are a bunch of CMakeLists.txt files in the source dir and probably in several subdirs, but there may also be additional CMake scripts, usually ending in .cmake and stored in a special CMake directory. By default CMake does not alter any file in the source directory and doesn't add new ones, either.

Build directory

This directory is where all compiler outputs are stored, which includes both object files as well as final executables and libraries. CMake also stores several files of its own here, including its cache. The location of the build dir is entirely up to you, and you can have more than one build directory for the same source directory. This is useful when you need to use builds with differing build options. You can even use the source dir as the build dir, but this will clutter the source dir with CMake and compiler outputs which I don't recommend. Better keep the source dir clean!

Install directory

Traditionally Unix builds are finished with a call of 'make install' which copies all relevant files from the built project you need for your everyday use to a clean place. Basically it separates all necessary files from the "garbage" which is output in the build directory. CMake generates an equivalent install target on all platforms, even on platforms which don't traditionally use an install step (like Visual Studio). The location of the install directory is governed by the CMake cache variable CMAKE_INSTALL_PREFIX. Of course, installation is entirely optional and only takes place if you build the install target.

Using CMake

Building a project with CMake always involves the following steps: First you call CMake to have it process the source directory and prepare a build directory for you. During that process you can also change the variables in the CMake cache to influence the way the project will be built. After that CMake generates a native build chain for you in the build directory which you use to build, and possibly install, the project.

CMake frontends

To call CMake you may use one of several frontends that CMake provides. The most basic one is the cmake console program which is available on all platforms. CMake also ships with a wxWidgets based GUI frontend called cmake-gui, it is also available for all platforms, but some Linux distributions don't yet ship it in their cmake packages. Finally, there is an ncurses based frontend for Unix systems called ccmake. I personally recommend using cmake-gui, but either one will do the job.

cmake

cmake is a console program so you need to fire up a console to use it. Then, in the console, switch to your designated build directory. If it doesn't exist yet, create it. The most basic form of calling cmake looks like this:

cmake /path/to/source/dir


That is, cmake is run inside the build directory and given the path to the source directory as a command line option. The example above illustrates a full path from a Unix environment, you can of course also specify a relative path. On Windows, the command might look more like this:

cmake C:/path/to/source/dir


As you can see, even on Windows CMake is used to working with slashes (/) instead of backslashes (\) in paths, although it does understand backslashes, so you could have written the path with those if you prefer that.

CMake will now process the source directory and output a lot of status messages. If there are any errors (usually because a dependency library was not found), it will be printed in the console, so reading the output is recommended.

Once cmake is done your build directory should be ready for building the package. Without further command line options cmake will use a default generator for the platform (on Unix: Makefiles) and will also setup all cache variables with their default variables. You can at any time rerun cmake and pass additional command line options to change the generator or change the value of cache variables. Every rerun still needs to tell cmake which source dir to operate on, but after the initial pass you can instead give cmake the path to the build directory which is the current directory (.), so calling 'cmake .' suffices.

To change the generator, you should first run

cmake --help


This will print some command line help plus, at the end, it will list the available generators for your platform. On Linux, the output might look like this:

The following generators are available on this platform:
    Unix Makefiles              = Generates standard UNIX makefiles.
    CodeBlocks - Unix Makefiles = Generates CodeBlocks project files.
    Eclipse CDT4 - Unix Makefiles
                                = Generates Eclipse CDT 4.0 project files.
    KDevelop3                   = Generates KDevelop 3 project files.
    KDevelop3 - Unix Makefiles  = Generates KDevelop 3 project files.


Now, to select a different generator you need to call cmake with the -G option and pass it the full name of the generator you want to use. For example, to have cmake generate CodeBlocks build files, you'd call

cmake . -G "CodeBlocks - Unix Makefiles"


To change the contents of a CMake cache variable, the -D option is available. Say you want to change the contents of CMAKE_BUILD_TYPE, then you would call the following:

cmake . -DCMAKE_BUILD_TYPE="Debug"


To change multiple variables you can either run cmake multiple times each with a different variable (since their contents are cached, cmake remembers changes from before) or you can supply the -D option several times.

cmake also has an interactive mode which you start by typing

cmake . -i


In this mode, cmake will present to you all cache variables and ask you if you want to keep the current value or enter a new one.

ccmake


Like cmake, ccmake is a console program, but it uses ncurses to make editing the cache variables more accessible. It inherits cmake's command line options, so anything said above about cmake essentially also applies to ccmake.


To start, type

ccmake /path/to/source/dir


which will process the source dir and prepare the current directory as the build dir. Furthermore you will be presented with a ncurses UI which lets you edit the contents of the CMake cache. Use the cursor keys to navigate to any variable you want to change, then press Enter. If the variable is boolean, this will switch its state from ON to OFF or vice versa. Otherwise you can type in the new value of the variable and press Enter again to finish your edit. A short help text to each variable is displayed at the bottom in a status bar. Once you are done, press 'c' to reconfigure the build, then press 'g' to generate the native build system and exit ccmake. If you want to quit without generating, press 'q'.

By default, ccmake only displays a part of the available cache variables. Others may be marked as advanced settings and will only be shown to you if you press 't' - this toggles the display of advanced variables.

To change the generator used by ccmake, you need to pass the same command line argument as with cmake, so read on up above.

cmake-gui

cmake-gui is a true graphical frontend for CMake, that is you don't have to mess with command line options. Once you've started cmake-gui, it will look similar to the first picture below. The first thing to do is to tell it the location of the source and build directories which is done via the two path selectors at the top. I recommend you always select the build directory first because if you choose a build directory which has been configured before cmake-gui may override your choice of the source directory. Therefore, choose the build directory first, then the source directory.

Next, press the button 'Configure' in the lower left. This will present you with the dialog shown in the second image; here you have to choose the CMake generator you want to use. Once selected, press 'Ok'. CMake will now start its first pass over the source directory and prepare the build directory and the CMake cache. After that cmake-gui will present you with the available cache variables which you can modify to configure the build. By default cmake-gui shows only non-advanced options, just like ccmake. However, there is a drop-down list right above the list of variables. Its standard setting is 'Simple View'. You can change it to either 'Advanced View' or 'Grouped View', the former will list all available variables in alphabetical order while the latter groups variables which start with the same prefix. Personally I find 'Grouped View' the most pleasing to work with, but you can decide for yourself.

Boolean variables are displayed as a check box which you can click on to change its value from ON to OFF or vice versa. Any other variable will display its current variable, double-click on any entry in order to edit its value. Once you are satisfied with your choices click 'Configure' again. Finally, click the button 'Generate' right next to have CMake create the native build chain.

The text area at the very bottom of cmake-gui displays the output of CMake. This is the same output which the console variant cmake will give you, and I highly recommend skimming through the lines to see if anything might not have gone as you want it to. Specifically, CMake usually presents its finding of dependencies here. Now, if a required dependency is not found, CMake will usually present you with an error message which cmake-gui displays in a separate dialog box. But optional dependencies might go unnoticed except for status messages displayed here, so keep your eye on that.

Fresh start of cmake-gui
Fresh start of cmake-gui

Select the CMake generator to use
Select the CMake generator to use

Configure the build
Configure the build

Grouped view of cache variables
Grouped view of cache variables

Common CMake build options

The contents of the cache, i. e. the variables which you can edit with either CMake frontend to alter the build procedure, come from different sources. Most of the variables you would actually want to modify are provided by the project itself. Ogre, for example, provides several variables to alter settings like thread support, allocator strategies, double precision etc.. Other cache entries are provided when CMake searches for dependencies (see below). And there are some variables which CMake itself provides. Many of them contain platform-specific settings which you should not normally need to modify. But there are a few variables common to all CMake builds which you might find useful.

The first of them is the variable CMAKE_INSTALL_PREFIX. This variable contains the path to the install directory and defaults to /usr/local on Unix systems. If you intend to install the project, you should set this to wherever you want to install it.

Then there is CMAKE_BUILD_TYPE. This variable does not exist for all platforms, more specifically it usually applies to Makefile-based builds. It sets the type of build, i. e. debug or release, that you want to do. The Visual Studio generators don't have it because switching between build types is possible in the IDE itself. But if the variable is present, then you should enter one of the following possible values:

  • Release - Release build
  • Debug - Debug build
  • RelWithDebInfo - Release build, but contains debug symbols. This one may be useful on Unix systems if you don't want to build a separate, full debug build.
  • MinSizeRel - Release build optimised for binary size


For Unix Makefile builds you will find two boolean options CMAKE_COLOR_MAKEFILE and CMAKE_VERBOSE_MAKEFILE. The first one has CMake produce Makefiles which display coloured status messages during build. This is a good idea because it makes the output more readable, and thus it is default on. If you don't like it or it doesn't work correctly with your terminal, switch it off. CMAKE_VERBOSE_MAKEFILE will, if switched on, print the full command line of each command executed during the build, similar to what many traditional Makefiles do. Switch it on if you want to.

Finally, some projects (including Ogre) provide the option to automatically generate binary packages or installers after compilation. This is possible through the use of CPack, a companion software to CMake. If the project has CPack support enabled, you will see several variables beginning with CPACK_ in the cache, each of which toggles a specific package format that CPack will generate. For example, on Unix platforms you might find variables like CPACK_BINARY_DEB, CPACK_BINARY_RPM, CPACK_BINARY_TGZ, whereas Windows offers CPACK_BINARY_NSIS. Switch on the ones which you want CPack to generate. CPack package building is done via an additional build target called package. It is not automatically involved in a standard build, you have to do it manually. If you are using Visual Studio, then you will find an additional target called PACKAGE in your solution file. Simply select to build it, and the packages will be generated. On Unix, type

make package

to start package creation.

Finding dependencies

CMake projects can automatically search for the location of dependency libraries to setup the location of include directories and libraries without hardcoding them to some sort of guesses. CMake, when asked to look for a dependency, searches its module path for special find scripts which are named Find${PACKAGE}.cmake (with ${PACKAGE} replaced by the actual package name). Ogre, for example, ships a number of these find scripts for its own dependencies in the directory CMake/Packages.

You don't need to understand the exact nature of how these find scripts work (unless you want to write one yourself), but virtually every find script adds the following variables to the CMake cache:

  • ${PACKAGE}_INCLUDE_DIR - contains the path to the include directory for this package as determined by the find script.
  • ${PACKAGE}_LIBRARY - contains the path to the library you need to link against to use this package.
  • Sometimes, instead of ${PACKAGE}_LIBRARY you might also get something like ${PACKAGE}_LIBRARY_RELEASE and ${PACKAGE}_LIBRARY_DEBUG which point to different link libraries for debug and release builds.
  • Also, sometimes a package might consist of more than one component or library, so you may get multiple variables of the above nature for each of them.


Now, the find scripts are not omniscient. If you happen to have installed a dependency in a location which is not a standard location for that package or for libraries in general, the find script may fail to find the package even though it's present on your computer. If this happens, all of the above variables will be set to the value ${SOMETHING}-NOTFOUND. You are now left with two options, either you fill in the variables with the right locations manually - or you try to help the find script locate the package. How exactly you might do the latter depends on the particular find script. Often there is a certain environment variable you can set to point to the install location of the package, something like ${PACKAGE}_HOME or ${PACKAGE}_ROOT. But this is not standardised, so you have to look at the find script's documentation or even at the script itself. The environment variables you can use to help Ogre's find scripts are documented in the section Building Ogre With CMake.