Skip to content

Notes on CMake (part 1)

Published: at 11:58 AM

Notes on CMake (part 1)

Table of contents

Open Table of contents

Introduction

CMake is a cross-platform build system generator that follows a two-step process:

Project Setup

A fundamental part of CMake is the concept of separate source and build directories:

mkdir build
cd build
cmake -G "Unix Makefiles" ..

You can also set the CMAKE_GENERATOR environment variable to specify your preferred generator.

Typical output after configuration:

-- Configuring done
-- Generating done
-- Build files have been written to: /some/path/build

Running the Build

cmake --build /path/to/build --config Debug --target MyApp

Basic Project Structure

A minimal CMake project:

cmake_minimum_required(VERSION 3.12)
project(MyApp)
# Define an executable target
add_executable(MyExe main.cpp)

Building Targets

Creating Libraries

add_library(targetName [STATIC | SHARED | MODULE] source1 [source2...])

Linking & Dependencies

Libraries can have different types of dependency relationships:

target_link_libraries(targetName <PRIVATE|PUBLIC|INTERFACE> item1 [item2] [...])

Example

# MyLib uses Boost internally and exposes Eigen in its public API
target_link_libraries(MyLib 
        PRIVATE Boost::boost
        PUBLIC Eigen3::Eigen
)

Working with Include Directories

The target_include_directories command specifies include directories for a target:

Syntax

target_include_directories(<target> 
        [SYSTEM] [BEFORE] 
        <INTERFACE|PUBLIC|PRIVATE> [items...]
)

Dependency Propagation

ScopeApplies To
PRIVATEOnly the target itself
PUBLICTarget and any target linking to it
INTERFACEOnly targets that link to this target

Examples

Basic Usage:

# Library with public headers
add_library(MyMath STATIC src/math.cpp)
target_include_directories(MyMath 
        PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include
        PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/src
)

Header-Only Library:

add_library(HeaderOnly INTERFACE)
target_include_directories(HeaderOnly 
        INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}/include
)

Advanced Features

Best Practices

Variables & Directories

CMake provides predefined variables for directory paths:

# Set a variable
set(varName value)
# Set an environment variable
set(ENV{PATH} "$ENV{PATH}:/opt/myDir")

Directory Variables

Adding Subdirectories

add_subdirectory(source_dir [binary_dir] [EXCLUDE_FROM_ALL])

Previous Post
Modern C++ Error Handling
Next Post
Managing File Permissions with Docker Containers