Skip to content
C++

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 clangd

Targets

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 -V

Useful 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 release

Common 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)
Edit on GitHub