Skip to main content

CMake Cheat Sheet

Introduction

This cheat sheet provides a comprehensive overview of essential CMake commands, best practices, and usage examples.
Each section includes detailed explanations and direct links to the official
CMake documentation to help you better understand and utilize CMake
in your projects.


1. Basic Commands

cmake_minimum_required(VERSION <version>)

This command sets the minimum version of CMake required to process your project.
It prevents the project from being configured with an outdated version that
might lack features needed by your CMake scripts.

Example:

cmake_minimum_required(VERSION 3.21.2)

project(<name> [VERSION <version>] [LANGUAGES <languages>])

Initializes the project by setting its name, version, and programming languages.
It also defines useful variables like ${PROJECT_NAME} and ${PROJECT_VERSION}
for use later in your scripts.

Example:

project(MyProject VERSION 1.0 LANGUAGES CXX)

2. Create Targets

add_library(<name> [STATIC | SHARED | MODULE] source1 source2 ...)

Creates a library target from the provided source files. You can choose between
a static, shared, or module library based on your needs.

Example:

add_library(MyLibrary SHARED file1.cc file2.cc)

add_executable(<name> source1 source2 ...)

Defines an executable target. This command compiles the listed source files
into an executable binary.

Example:

add_executable(MyApp main.cc)

3. Target Management

target_compile_options(<target> [BEFORE | AFTER] <options>...)

Sets compile options for a specific target. The BEFORE and AFTER keywords determine whether the options are applied before or after the default options.

Example:

target_compile_options(MyLibrary PRIVATE -Wall -Wextra)

target_include_directories(<target> [PRIVATE | PUBLIC | INTERFACE] <directories>...)

Specifies include directories for a target. The visibility keywords control
how these directories are applied:

  • PRIVATE: Only used when compiling the target itself.
  • PUBLIC: Used when compiling the target and propagated to targets linking against it.
  • INTERFACE: Not used to compile the target but passed on to its consumers.

Example:

target_include_directories(MyLibrary PUBLIC "include/")
target_include_directories(MyLibrary PRIVATE "src/")

Links one or more libraries to a target, ensuring that the linker can find
all necessary symbols during the build process.

Example:

target_link_libraries(MyApp PRIVATE MyLibrary)

target_sources(<target> [PRIVATE | PUBLIC | INTERFACE] sources...)

Appends source files to a target. The visibility keywords determine how the sources are used by the target and its consumers.

Example:

target_sources(MyLibrary PRIVATE file.cc)

set_target_properties(<target> PROPERTIES <prop1> <value1> ...)

Sets properties for a target. These properties can include custom build settings, compiler flags, or other target-specific configurations.

Example:

set_target_properties(MyLibrary PROPERTIES CXX_STANDARD 17)

4. CMake Variables

1. Set Variables

set(<variable> <value> [CACHE <type> <docstring> [FORCE]])

Assigns a value to a variable. When used with the CACHE option, the variable
persists across CMake runs and can be modified by users during configuration.

Example:

set(MY_VERSION "1.0" CACHE STRING "Version of MyProject")

option(<option_variable> "Description" [value])

Defines a boolean option that users can toggle during the configuration process.
Options are typically used to enable or disable features.

Example:

option(ENABLE_FEATURE "Enable special feature" ON)

2. Builtin Variables

CMAKE_SOURCE_DIR

The root directory of the project where the top-level CMakeLists.txt file is located.

CMAKE_BINARY_DIR

The directory where CMake generates build files and stores build artifacts.

CMAKE_CURRENT_SOURCE_DIR

The directory containing the currently processed CMakeLists.txt file.

CMAKE_CURRENT_BINARY_DIR

The directory where the currently processed CMakeLists.txt file generates build files.

CMAKE_PROJECT_SOURCE_DIR

The source directory of the current project.

CMAKE_CXX_COMPILER_VERSION

The version of the C++ compiler being used.

CMAKE_CXX_STANDARD

The C++ standard version used for compiling the project.

CMAKE_LIBRARY_OUTPUT_DIRECTORY

The directory where shared libraries are built.

CMAKE_ARCHIVE_OUTPUT_DIRECTORY

The directory where static libraries are built.

CMAKE_RUNTIME_OUTPUT_DIRECTORY

The directory where executables are built.

CMAKE_PROJECT_VERSION

The version of the project specified in the project() command.

CMAKE_PROJECT_DESCRIPTION

The description of the project specified in the project() command.


5. Linking External libraries

find_library(<var> name1 [path1 path2 ...])

Searches for a library and sets a variable with the library's full path. This command is useful when you need to link against a specific library.

Example:

find_library(LIB_BOOST filesystem)

find_package(<package> [version] [EXACT] [QUIET] [MODULE] [REQUIRED] [COMPONENTS <components>...])

Searches for a package and sets variables with information about the package's location, version, and components. The REQUIRED option can be used to stop the configuration process if the package is not found.

Example:

find_package(Boost 1.75 REQUIRED COMPONENTS filesystem)

After finding the library, you can link it to your target using target_link_libraries.

Example:

target_link_libraries(MyApp PRIVATE Boost::filesystem)

6. Cmake advanced features

FetchContent

CMake’s FetchContent module simplifies the process of downloading and incorporating external dependencies (e.g., from GitHub) without manual submodule management.

Example:

include(FetchContent)

FetchContent_Declare(
ExternalLibrary
GIT_REPOSITORY https://github.com/example/external-library.git
GIT_TAG v1.2.3
)
FetchContent_MakeAvailable(ExternalLibrary)

add_executable(MyApp main.cc)
target_link_libraries(MyApp PRIVATE ExternalLibrary)

add_custom_target()

Creates a custom target that does not produce any output files but can be used to run custom commands during the build process.

Example:

add_custom_target(GenerateConfig
COMMAND ${CMAKE_COMMAND} -E copy_if_different
${CMAKE_SOURCE_DIR}/config.ini
${CMAKE_BINARY_DIR}/config.ini
)

7. Tips and Best Practices

  • Modularity:
    Organize your project into subdirectories using add_subdirectory()
    to keep your CMake files manageable and maintainable. Be careful subdirs is deprecated.

  • Target-based Approach:
    Use target_* commands (like target_include_directories and target_compile_options) to precisely control properties and dependencies.

  • Consistent Variable Naming:
    Use descriptive, clear names (preferably in uppercase for global variables)
    to avoid conflicts and improve readability.

  • Document Your Code:
    Comment your CMake files thoroughly, especially in complex sections,
    to assist future maintenance and collaboration.


This cheat sheet should serve as a robust foundation for learning and using CMake effectively.
For additional details on each command and more advanced topics, always refer to the official CMake documentation.