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/")
target_link_libraries(<target> ... <item>...)
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 usingadd_subdirectory()
to keep your CMake files manageable and maintainable. Be carefulsubdirs
is deprecated.Target-based Approach:
Usetarget_*
commands (liketarget_include_directories
andtarget_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.