A brief overview of how CMake works. More...
A brief overview of how CMake works.
Table of contents:
CMake
is a tool designed to help developers get rid of the challenges associated with writing Makefiles
in projects. CMake
is designed to be portable across many types of systems, and can generate native build scripts for many different compilers on several different operating systems. We will be giving a cursory overview of the CMake
and explain how you can use it with your own client applications.
Directory structure
A project directory typically contains the following subdirectories:
- src : Contains the source code that gets compiled. Often times, the
src
folder contains information for only one executable or libarary, but it is possible to have multiple executables per directory. - doc : Contains the project documentation. If you use doxygen or any other program for autogenerating your documentation, it is a good idea to build a
Makefile
so you can runmake
doc
to automatically generate the documentation.
Player has a slightly different (and larger directory structure), which works with generally the same principles.
Configuration files
CMake uses various CMakeLists.txt files, usually one in each directory of the project. These files contain logic to set build options, resolve external project dependencies, and add executable and library targets. Custom targets and macros can also be defined and included into the CMake
files.
A brief example
Sometimes the best way to explain a topic is by showing an example. Here, we will be building a project that uses CMake
to build a c++ client application. All of the code for this example is include in examples/tutorials/cmake
Base directory
CMake
requires at least one CMakeLists.txt file for project configuration. Generally, projects distribute the configuration, and place a CMakeLists.txt in each subdirectory of the source tree as well. This allows you to keep things modular: the base directory CMakeLists.txt can handle setting global configuration (project name, version, project dependency discovery), and the subdirectory files can handle.
The command CMAKE_MINIMUM_VERSION defines the minimum version of CMake
that is required to process the CMakeLists.txt file. This is to handle CMake
API compatibility; as new functions are added, older versions of CMake
won't be able process newer files. In general, we recommend version 2.6 and above.
The PROJECT macro sets your project's name. This can be useful in setting project install directories, but is not required. The PROJECT_VERSION variable is similar; if you're not creating a large project you probably don't need to worry about these variables.
The CMAKE_C_FLAGS and CMAKE_CXX_FLAGS are the build flags that will be applied to all C and C++ files in the project. You can set the CMake
variable CMAKE_BUILD_TYPE to "DEBUG" or "RELEASE" to switch between the two types of build flags. This can be accomplished in the ccmake
curses-based UI, or by using the -D option on the CMake
command line. For example:
$ cmake -D CMAKE_BUILD_TYPE=RELEASE
CMake
does not generate a "make uninstall" target by default. ADD_CUSTOM_TARGET allows you to add uninstall target. This particular method was borrowed from the CMake FAQ.
Finally, the ADD_SUBDIRECTORY commands tell CMake
to traverse to the "doc" and "src" subdirectories and process the CMakeLists.txt files in those directories.
- Note
- If you are installing Player on a machine, you need to make sure that the PKG_CONFIG_PATH that the code installed to is included in your search path. If you are using a bash shell, you can enter the following (or something similar) in your ~/.bashrc.
# for .pc in /usr/local export PKG_CONFIG_PATH=$PKG_CONFIG_PATH:/usr/local/lib/pkgconfig/
Source directory
A CMakeLists.txt
contains directives on how to build, link, and install libraries and executables. We will discuss some of the macros that Player includes for building plugin drivers and client programs, but the rest are beyond the scope of the document. The following CMakeLists.txt file builds a Player C++ client program and a Player example driver library.
Setting the CMAKE_MODULE_PATH tells CMake where it can search for additional modules when the INCLUDE command is used. If Player isn't installed to /usr, the path where Player is installed needs to be added so CMake
will be able to find Player's CMake
modules.
The INCLUDE command will load a CMake
module for use in your CMakeLists.txt. The UsePlayerC++ and UsePlayerPlugin CMake
modules provide useful macros for building and linking C++ clients and plugin drivers, respectively.
PLAYER_ADD_PLAYERCPP_CLIENT is one of the macros in UsePlayerC++. It uses the ADD_EXECUTABLE command from CMake
to create an executable client program, and handles adding all of the include directories and link libraries needed to compile against Player. More details about the macros Player provides can be found on the Player wiki.
Generating documentation
To demonstrate another aspect of the CMakeLists.txt
files we will setup code to allow you to run the command make
doc
and build doxygen comments. To use Doxygen to automatically generate documentation you typically type the command:
$ doxygen example.dox
where example.dox is a doxygen configuration file typically generated by a tool such as doxywizard
. To accomplish the same thing with your Makefile
, you can utilize the fact that you can create custom build targets with any arbitrary commands using @ CMake. The following creates a rudimentary build target to build documentation using Doxygen:
Generating the build scripts
You need to run the CMake
program in order to generate project @ Makefiles from the @ CMakeLists.txt files. Generally, it is encourged to do an "out of tree build." This constitutes creating a separate folder in the base directory of your project, usually called build. From this build folder, you can invoke CMake
and generate the build scripts. The out-of-tree build has the advantage of keeping all of the generated build scripts away from the source files, so they can be easily removed or ignored using a .gitignore or .svnignore. You can do an out-of-tree build like this:
$ mkdir build $ cd build $ cmake ..
After generating the scripts, you can run the typical make
command as usual to build the project.
Build options
After successfully running the CMake
program the following options are avaliable for make
make
: Builds the project and creates the executables and libraries.make
clean
: Cleans the project i.e removes all the executables.make
install
: Builds and installs the project i.e the executable is copied in the /prefix/bin,headers in /prefix/include and libraries in /prefix/lib where prefix is usually /usr/local.make
uninstall
: Uninstalls the project i.e removes the files added to /prefix/bin, /prefix/include and /prefix/lib directories.make
doc
: Creates project documentation