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]<INTERFACE|PUBLIC|PRIVATE> [items1...][<INTERFACE|PUBLIC|PRIVATE> [items2...] ...])​

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.

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.