devl.cz/ cmake

CMake

Create minimal CMakeLists.txt:

cmake_minimum_required(VERSION 3.0)
project(hello_world)

set(SOURCE_FILES main.cpp)
add_executable(${PROJECT_NAME} ${SOURCE_FILES})

Configure out-of-source build:

mkdir build
cd build
cmake ..

Build the project:

make

More information:

Finding external libraries

Require SDL2:

find_package(sdl2 REQUIRED)
target_include_directories(${PROJECT_NAME} PRIVATE ${SDL2_INCLUDE_DIRS})
target_link_libraries(${PROJECT_NAME} ${SDL2_LIBRARIES})

Alternatively, using pkg-config:

include(FindPkgConfig)
pkg_search_module(SDL2 REQUIRED sdl2)
target_include_directories(${PROJECT_NAME} PRIVATE ${SDL2_INCLUDE_DIRS})
target_link_libraries(${PROJECT_NAME} ${SDL2_LIBRARIES})

Adding support for non-standard library

Create cmake-modules dir in your project root and add it to CMakeLists.txt:

list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake-modules)

Create cmake-modules/FindLiquidFun.cmake:

# Try to find LiquidFun.
# Once done this will define:
#   LIQUIDFUN_FOUND
#   LIQUIDFUN_INCLUDE_DIRS
#   LIQUIDFUN_LIBRARIES

set(LIQUIDFUN_ROOT_DIR ~/src/liquidfun)
find_path(LIQUIDFUN_INCLUDE_DIR Box2D/Box2D.h
        ${LIQUIDFUN_ROOT_DIR}/liquidfun/Box2D)
find_library(LIQUIDFUN_LIBRARY NAMES liquidfun PATHS
        ${LIQUIDFUN_ROOT_DIR}/liquidfun/Box2D/build/Box2D/Release)

find_package_handle_standard_args(liquidfun DEFAULT_MSG
        LIQUIDFUN_LIBRARY LIQUIDFUN_INCLUDE_DIR)
mark_as_advanced(LIQUIDFUN_ROOT_DIR LIQUIDFUN_LIBRARY LIQUIDFUN_INCLUDE_DIR)
set(LIQUIDFUN_LIBRARIES ${LIQUIDFUN_LIBRARY})
set(LIQUIDFUN_INCLUDE_DIRS ${LIQUIDFUN_INCLUDE_DIR})

Then use it:

find_package(LiquidFun REQUIRED)
target_include_directories(${PROJECT_NAME} PRIVATE ${LIQUIDFUN_INCLUDE_DIR})
target_link_libraries(${PROJECT_NAME} ${LIQUIDFUN_LIBRARY})

More information, extra modules:

Debugging

To print build commands, either set a flag:

set(CMAKE_VERBOSE_MAKEFILE ON)

Or call make with an argument:

make VERBOSE=1

To quickly print contents of some variable:

message(WARNING "Test: ${SDL2_INCLUDE_DIRS}")

There are various debugging arguments to cmake command:

-Wdev               Enable developer warnings.
--debug-output      Put cmake in a debug mode.
--trace             Print a trace of all calls made and from where.

Draw dependency graph using Graphviz:

cmake --graphviz=deps.dot ..
dot -T png -o deps.png deps.dot

References:

Adding custom options

Define the option:

option(WithPython "Build with embedded Python." ON)

Then set it in configuration phase:

cmake -DWithPython=OFF

Checking Target Platform

Use CMAKE_SYSTEM_NAME to check target platform:

if(CMAKE_SYSTEM_NAME STREQUAL "Linux")
# ...
endif()

This is cross-compile friendly - it checks the system for which we’re building. The system on which we’re building is CMAKE_HOST_SYSTEM_NAME.

There are also some shortcuts:

These shortcuts are much easier to type:

if(APPLE)
# ...
endif()

We can also define our own shortcuts:

if(CMAKE_SYSTEM_NAME STREQUAL "Linux")
    set(LINUX True)
endif()

Note that CMake tests the target platform by compiling a source file with macros like #if defined(__APPLE__). This source file can be found in CMakeFiles.

References: