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 suggests 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 in 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 the compiler include search path.
  • Create an executable file from main.cpp into ./build/bin/.
  • Create a static/dynamic library (in the example, 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})
cmake demo

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.