CMake
01 Oct 2016CMake is an open source cross platform tool to build software projects. CMake generates build pipeline for the platform, which is then used to build the project. In simpler language, CMake generates files required to build the project. For a C++ project, the output of CMake is a build pipeline which can be anything from a Visual Studio Project to Linux Makefiles, based on the selected generator.
CMake introduces a lot of complexity into the build system but fear not as this complexity is abstracted from the user. A user is never expected to modify the generated build pipeline.
To use CMake, a CMakeLists.txt file is required in the source directory of the project. This file contains all the build instructions.
A recommended way to build a project is to create a new directory named build
, which is different from the source directory. From the build directory, execute cmake <Source Directory>
This will generate a build pipeline. For the sake of simplicity, let’s assume we are on a linux machine, and the build pipeline generated is a Makefile. Generating build pipeline in a seperate build directory have the advantage of seperating the build files from project source files. All the build artifacts are in this directory, and can be deleted for cleanup.
The most basic CMake for a project is:
cmake_minimum_required(VERSION 2.9)
project(BasicProject)
add_executable(BasicProject, main.cpp)
Some Interesting Cmake Command Arguments
cmake <source directory> -p
runs the script but don’t generate a pipeline.cmake <source directory> -j n
, runs the build process on n threads in parallel, if possible.
CMake is more like a scripting language and is very flexible. Let’s go over the basic building blocks of CMake Scripting.
message
message("Building Core library.")
message prints the message. Very useful for printing status messages.
Variables
Every varible in CMake is a string. A variable is reference by specifying the name of variable in ${}. This is also known as variable reference. Variables can be set by:
- Set command
set (Number, 42)
This sets the variable Number to 42. The statementmessage("The Ultimate Answer is ${Number}")
prints The Ultimate Answer is 42. - Varibles can be defined on command line
$ cmake -DNumber 42
Quotes around arguments are optional as long as there are no spaces or reference variable.
Flow Control
Cmake supports if
statement and while
loop.
if(Linux)
message("Building on Linux")
endif()
while(num LESS 42)
message("Number is still less than 42.")
endwhile()
Including Scripts
include ( <FileName.cmake> )
command is used to load and execute CMake from other the file provided. This is generally used to find third party packages. For example, a project using Boost, may have include (Boost.cmake)
which can be used to find boost installation before building.
add_subdirectory ( <source subdirectory> )
creates a new scope and executes the CMakeLists.txt from the subdirectory.
Include Directories
To set up the include directories include_directories ( <directoryName> )
is used.
Libraries
To set up the link library directories (just like LD_LIBRARY_PATH) link_directories ( <directoryName> )
is used.
And to link libraries, target_link_libraries( <target> PRIVATE "lib1.a lib2.a")
Targets
add_executable
, add_library
, add_custom_target
commands defines targets.
For example,
add_executable (MyBinary, MyBinary.cpp) \\Creates binary named MyBinary
add_executable (CoolStuffBinary, CoolStuff.cpp) \\Creates binary named MyBinary
add_library (MySharedLib, SHARED, SharedLibCode.cpp) \\Creates Shared library named MySharedLib.so
add_library (MyStaticLib, STATIC, SharedLibCode.cpp) \\Creates Shared library named MyStaticLib.a
Here CMake creates build targets for each executable. By default an all
target is also created is executed if no specific target is specified.
pending stuff about custom_target
Custom Commands
pending explanation
A self-explanatory CMakeLists.txt Example
Scratching the Surface
There is so much more in CMake, that this post can barely scratch the surface. Some other interesting features in cmake include generators, regular expressions etc.