CMake Quick Reference
CMake cheatsheet — targets, properties, find_package, FetchContent, install, generator expressions, and common patterns.
Project Setup
cmake
cmake_minimum_required(VERSION 3.25)
project(MyApp VERSION 1.2.3 LANGUAGES CXX)
set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)
set(CMAKE_EXPORT_COMPILE_COMMANDS ON) # for clangdTargets
cmake
# Executable
add_executable(app src/main.cpp src/util.cpp)
# Static library
add_library(mylib STATIC src/lib.cpp)
# Shared library
add_library(mylib SHARED src/lib.cpp)
# Header-only (interface)
add_library(headers INTERFACE)
# Alias — consistent :: naming
add_library(MyProject::mylib ALIAS mylib)Target Properties
cmake
target_include_directories(mylib
PUBLIC include/ # consumers inherit
PRIVATE src/ # only mylib sees
INTERFACE api/ # only consumers see
)
target_compile_options(mylib PRIVATE -Wall -Wextra -Werror)
target_compile_definitions(mylib PRIVATE MY_LIB_INTERNAL=1)
target_compile_features(mylib PUBLIC cxx_std_20)
target_link_libraries(app
PRIVATE mylib # not propagated
PUBLIC dep # propagated to consumers
)Variables and Options
cmake
set(MY_VAR "value")
set(MY_LIST a b c) # list
option(ENABLE_TESTS "Build tests" ON)
# Cache variable (survives cmake re-runs, visible in cmake-gui)
set(PORT 8080 CACHE STRING "Server port")
# From environment
set(CC $ENV{CC})
# Check
if(DEFINED MY_VAR)
if(MY_VAR STREQUAL "value")
if(ENABLE_TESTS)Conditionals and Loops
cmake
if(UNIX AND NOT APPLE)
# Linux
elseif(APPLE)
# macOS
elseif(WIN32)
# Windows
endif()
foreach(item ${MY_LIST})
message("${item}")
endforeach()
# Range
foreach(i RANGE 1 10)
message("${i}")
endforeach()Finding Packages
cmake
# Config-mode (preferred — uses PackageConfig.cmake)
find_package(OpenSSL REQUIRED)
target_link_libraries(app PRIVATE OpenSSL::SSL OpenSSL::Crypto)
# Module-mode (FindXxx.cmake in CMake's modules)
find_package(Threads REQUIRED)
target_link_libraries(app PRIVATE Threads::Threads)
# With version
find_package(Boost 1.80 REQUIRED COMPONENTS filesystem)
target_link_libraries(app PRIVATE Boost::filesystem)
# Optional
find_package(ZLIB)
if(ZLIB_FOUND)
target_link_libraries(app PRIVATE ZLIB::ZLIB)
endif()FetchContent
cmake
include(FetchContent)
FetchContent_Declare(fmt
GIT_REPOSITORY https://github.com/fmtlib/fmt.git
GIT_TAG 10.2.1
GIT_SHALLOW TRUE
)
FetchContent_MakeAvailable(fmt)
target_link_libraries(app PRIVATE fmt::fmt)Generator Expressions
cmake
# Config-based
$<CONFIG:Debug> # 1 in Debug, 0 otherwise
$<$<CONFIG:Release>:-O3> # -O3 only in Release
# Compiler-based
$<$<CXX_COMPILER_ID:GNU>:-Wall>
$<$<CXX_COMPILER_ID:Clang,GNU>:-Wpedantic>
# BUILD vs INSTALL paths
$<BUILD_INTERFACE:${CMAKE_SOURCE_DIR}/include>
$<INSTALL_INTERFACE:include>
# Target property
$<TARGET_FILE:myapp> # full path to executable
$<TARGET_NAME_IF_EXISTS:dep>Install
cmake
install(TARGETS myapp mylib
RUNTIME DESTINATION bin
LIBRARY DESTINATION lib
ARCHIVE DESTINATION lib
INCLUDES DESTINATION include
)
install(DIRECTORY include/ DESTINATION include
FILES_MATCHING PATTERN "*.hpp")
install(EXPORT MyTargets
FILE MyTargets.cmake
NAMESPACE My::
DESTINATION lib/cmake/My
)Testing
cmake
enable_testing()
add_executable(tests test/main.cpp)
target_link_libraries(tests PRIVATE GTest::gtest_main mylib)
include(GoogleTest)
gtest_discover_tests(tests)
# Run: cmake --build build && ctest --test-dir build -VUseful Commands
bash
# Configure
cmake -B build -DCMAKE_BUILD_TYPE=Release -GNinja
# Build
cmake --build build --parallel $(nproc)
# Install
cmake --install build --prefix /usr/local
# Test
ctest --test-dir build -j4 --output-on-failure
# List cache
cmake -B build -L
# Presets
cmake --preset release
cmake --build --preset releaseCommon Patterns
cmake
# Compiler warnings interface target
add_library(project_warnings INTERFACE)
target_compile_options(project_warnings INTERFACE
$<$<CXX_COMPILER_ID:GNU,Clang>:-Wall -Wextra -Wpedantic -Werror>
$<$<CXX_COMPILER_ID:MSVC>:/W4 /WX>
)
# C++ standard interface target
add_library(project_options INTERFACE)
target_compile_features(project_options INTERFACE cxx_std_23)
set_target_properties(project_options PROPERTIES
INTERFACE_CXX_EXTENSIONS OFF
)
# Apply to all targets
target_link_libraries(mylib PRIVATE project_warnings project_options)
# Subdirectories
add_subdirectory(src)
add_subdirectory(tests)
add_subdirectory(third_party)