CMake is a cross-platform build system generator of Makefiles, projects specify their build process with platform-independent CMake listfiles included in each directory of a source tree with the name CMakeLists.txt

Executable

$ cmake [options] (<path-to-source> | <path-to-existing-build>)

Assuming that the directory contains

.
├── CMakeLists.txt
└── main.cpp
#include <iostream>
using namespace std;
int main () {
  cout << "Hello world" << endl;
  return 0;
}

The minimal CMakeLists.txt file contains

cmake_minimum_required (VERSION 2.6)
project(Hello)
add_executable(${PROJECT_NAME} main.cpp)

Running cmake . creates a Makefile in the same directory whose recipes are cross platform commands, CMake's documentation suggest that the build is separated from the source

$ mkdir build
$ cd build
$ cmake ..

Running the default target in the makefile creates the executable Hello, note that this is done on the ./build/ directory

$ make
Scanning dependencies of target Hello
[ 50%] Building CXX object CMakeFiles/Hello.dir/main.cc.o
[100%] Linking CXX executable Hello
[100%] Built target Hello
$ ./Hello
Hello world

Useful variables

  • CMAKE_SOURCE_DIR - path to the top level of the source tree (default value ./)
  • CMAKE_BINARY_DIR - path to the top level of the build tree (default value ./build/)
  • CMAKE_RUNTIME_OUTPUT_DIRECTORY - path to the executable (usually set to ${CMAKE_BINARY_DIR}/bin/)
  • CMAKE_ARCHIVE_OUTPUT_DIRECTORY - path to the static libraries (code from static libraries is included in the executable, usually set to ${CMAKE_BINARY_DIR}/lib/)
  • CMAKE_LIBRARY_OUTPUT_DIRECTORY - path to the shared libraries (additional code required by the executable, usually set to ${CMAKE_BINARY_DIR}/lib/)

Project structure and organization

. project
├── build
├── include
│   └── project
│       └── World.hpp
└── src
    ├── World.cpp
    └── main.cpp

The CMakeLists.txt file should do the following

  • add the ./include path to compiler include search path
  • create an executable file from main.cpp into ./build/bin/
  • create an static/dynamic library (in the example is World.cpp) into ./build/lib/
  • link the library with the executable
cmake_minimum_required(VERSION 3.0)

project(runner)

set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin")
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/lib")
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/lib")

# the -I flag in gcc
include_directories(
  ${PROJECT_SOURCE_DIR}/include/
)

set(APP_SOURCES src/main.cpp)
set(LIB_SOURCES src/World.cpp)

# creates ./build/bin/runner
add_executable($${PROJECT_NAME} $${APP_SOURCES})

# shared library
set(LIBRARY_NAME World)
add_library($${LIBRARY_NAME} SHARED $${LIB_SOURCES})
target_link_libraries($${PROJECT_NAME} $${LIBRARY_NAME})

Complex CMake configuration

A complex CMake configuration will have multiple CMakeLists.txt files per directory

  • ./CMakeLists.txt - configures dependencies, platform specifics and output paths
  • ./src/CMakeLists.txt - configures the library to build

References
  • C++ project organisation (with gtest, c. (2016). C++ project organisation (with gtest, cmake and doxygen). [online] Stackoverflow.com. Available at: http://stackoverflow.com/a/13522826/3341726 [Accessed 5 Apr. 2016].