Short copy-pasteable CMake snippets ::: ${✂️}

Overview

CMake Snippets ${✂️}

Short copy-pasteable "Modern" CMake snippets.

These snippets are not comprehensive and are not a replacement for documentation.
Use them to avoid needing to memorize them.

New Project

Name your project and set the minimum CMake version

cmake_minimum_required(VERSION 3.4)
project(MyProj)

cmake_minimum_required(), project()

Default Build Type

Set default build type, e.g. Release. Turn on Debug with -DCMAKE_BUILD_TYPE=Debug

if(NOT CMAKE_BUILD_TYPE)
  set(CMAKE_BUILD_TYPE Release)
endif()

CMAKE_BUILD_TYPE

Adding #include Paths

Prefer per-target includes to scope-based commands:

target_include_directories(my_app PUBLIC mylib/include)

This command adds mylib/include to the my_app include search paths.

When another dependent target uses target_link_libraries() to link with a lib with INTERFACE or PUBLIC target_include_directories(), the linking target will automatically have the library include directories added.

Thus you should prefer target_include_directories() to the older command:

include_directories(my_app mylib/include)

include_directories() works at directory scope. All targets in this CMakeList.txt, as well as those in all subdirectories added after the point of its call, will have the path mylib/include added to their include path.

target_include_directories(), include_directories() SO-1, SO-2

Create Header Only Library

add_library(my_header_only_lib INTERFACE)                              # No sources provided
target_sources(my_header_only_lib INTERFACE my_header.hpp)             # Adds header files to target, will appear in IDEs
target_include_directories(my_header_only_lib INTERFACE my_header.hpp) # Allow lib dependent target to auto add includes too 

When another target uses target_link_libraries() to link with my_header_only_lib, the linking target will automatically have the library include directories added.

add_library(), target_sources(), target_include_directories(), SO-2

Setting C++ Standard

Set the default C++ standard for all targets:

set(CMAKE_CXX_STANDARD 17) # C++17

Set the C++ standard for a specific target my_app:

set_property(TARGET my_app PROPERTY CXX_STANDARD 17) # C++17

This is preferable to setting the compiler-specific commands such as -std=c++17.

CMAKE_CXX_STANDARD, CXX_STANDARD

Put Targets in IDE/Solution Folders

Turn on project folder support property and set each target to its named folder

set_property(GLOBAL PROPERTY USE_FOLDERS ON) # Turn on this feature
...
set_property(TARGET my_lib PROPERTY FOLDER "libs")
set_property(TARGET another_lib PROPERTY FOLDER "libs/3rdParty")
set_property(TARGET my_app PROPERTY FOLDER "utils")

USE_FOLDERS, FOLDER

Add Build Option

Adds a CMake togglable variable that will also appear in cmake-gui, for conditional build settings.
If the variable is set via the command line or the GUI the default initial value will be ignored:

option(ENABLE_PYTHON_BINDINGS "Build Python bindings" OFF)    # Adds option, sets default to OFF

if(ENABLE_PYTHON_BINDINGS)                            
    add_subdirectory(external_libs/pybind11)
endif()

This will create a toggleable check box in cmake-gui.
To toggle from the command line use cmake ... -DENABLE_PYTHON_BINDINGS=ON.

option()

(Unit) Testing

Activate testing

Activate testing support for ctest via enable_testing

Adding a test

Test programs are normal executable created via add_executable.

For that cmake knows an executable is a test it has to be registered as such. This is done via the add_test command.

Setting test properties

It is possible to add properties to a test, these are set via the set_tests_properties command.

  • WILL_FAIL true tells cmake that a test is expected to fail
  • TIMEOUT limits the test runtime to the number of seconds specified.

Example

enable_testing()
add_executable(mytest testcode1.cpp testcode2.cpp)
add_test(NAME myapp_mytest COMMAND mytest)
set_tests_properties(myapp_mytest TIMEOUT 1)

Running tests

If testing is enabled and at least one test has ben registered there is now a test target available, which can be invoked via make test in the build directory.

Alternative, running directly ctest in the build directory is also a possibility.

If there are multiple test binaries in a project it is possible to execute them in parallel. This works by the -j (jobs) command line switch.
ctest -j8 in case of running ctest, make test ARGS=-j8 to pass the switch via make test to ctest.

Providing Test Data Paths at Build Time

Sometimes we cannot generate the data for the tests at run time and need to load it from some folder. We can do this by creating a private build preprocessor variable for our unit test app.

In our CMakeLists.txt we add the path location in the repo (or any such similar info):

target_compile_definitions(unit_tests PRIVATE TEST_DATA_DIR=${PROJECT_SOURCE_DIR}/test_data)

and in our unit test source code we can use this flag as follows:

#ifndef TEST_DATA_DIR
#error "Must specify test data directory path in TEST_DATA_DIR."
#else
#define STRINGIFY(x) #x
#define TOSTRING(x) STRINGIFY(x)
constexpr const char* testDataFolder = TOSTRING(TEST_DATA_DIR);
#undef TOSTRING
#undef STRINGIFY
#endif

The constexpr (global) variable testDataFolder will hold the path to use at build time.

Profiling

If you are using MSVC you can use a generator expression to add /PROFILE to the link options for your target if RelWithDebInfo is the target.

if (MSVC) 
  target_link_options(my_target PRIVATE $<$<CONFIG:RELWITHDEBINFO>:/PROFILE>)
endif()

Note: target_link_options is from 3.13, you can use target_link_libraries if you're on an old version.
HT: @TartanLlama

You might also like...
curl cmake module libcurl build with msvc x86

curl-msvc Infomation curl cmake module libcurl build with MSVC10.0 arch (x86 | i386) source from https://github.com/curl/curl tags: curl-7_79_1 Usage

NeoWorld is a resampler using the CMake build system

NeoWorld is a resampler using the CMake build system. It's designed for utsu, OpenUTAU, and UTAU.

A CMake addon that avoids you writing boilerplate code for resource management.

SHader INJ(I)ector SHINJI (originally SHader INJector) is a CMake addon that avoids you writing boilerplate code for resource management and exposes s

A CMake starter template using CPM

Cmake Starter About A lightweight Cmake project meant for a binary application (not a shared library), tests with catch2 are configured, CPM is the pa

Non-intrusive CMake dependency management

cmodule Non-intrusive CMake dependency management. Normally CMake's find_package() looks for packages installed on host system (and compiled for host

Simple library for embedding static resources into C++ binaries using CMake

libromfs libromfs is an easy way to bundle resources directly into any C++ application and access them through a simple interface. The main advantage

Project to enable using CMake from a Maven build.

CMake-Maven-Project Introduction A Maven project for the CMake build system. It can be used by including it as a plugin within your Maven project's po

Autotools-style configure script wrapper around CMake

configure-cmake configure-cmake is an autotools-style configure script for CMake-based projects. People building software on Linux or BSD generally ex

Check for coding style issues in CMake files

cmakelint parses CMake files and reports style issues. cmakelint requires Python. Installation sudo pip install cmakelint Usage Syntax: cmakelint [--c

CMake checks cache helper modules – for fast CI CMake builds!

cmake-checks-cache Cross platform CMake projects do platform introspection by the means of "Check" macros. Have a look at CMake's How To Write Platfor

Cristian Adam 65 Dec 6, 2022
CMake scripts for painless usage of SuiteSparse+METIS from Visual Studio and the rest of Windows/Linux/OSX IDEs supported by CMake

CMake scripts for painless usage of Tim Davis' SuiteSparse (CHOLMOD,UMFPACK,AMD,LDL,SPQR,...) and METIS from Visual Studio and the rest of Windows/Lin

Jose Luis Blanco-Claraco 395 Dec 24, 2022
cmake-font-lock - Advanced, type aware, highlight support for CMake

cmake-font-lock - Advanced, type aware, highlight support for CMake

Anders Lindgren 39 Oct 2, 2022
cmake-avr - a cmake toolchain for AVR projects

cmake-avr - a cmake toolchain for AVR projects Testing the example provided The toolchain was created and tested within the following environment: Lin

Matthias Kleemann 163 Dec 5, 2022
Make CMake less painful when trying to write Modern Flexible CMake

Izzy's eXtension Modules IXM is a CMake library for writing Modern flexible CMake. This means: Reducing the amount of CMake written Selecting reasonab

IXM 107 Sep 1, 2022
CMake module to enable code coverage easily and generate coverage reports with CMake targets.

CMake-codecov CMake module to enable code coverage easily and generate coverage reports with CMake targets. Include into your project To use Findcodec

HPC 82 Nov 30, 2022
unmaintained - CMake module to activate certain C++ standard, feature checks and appropriate automated workarounds - basically an improved version of cmake-compile-features

Compatibility This library provides an advanced target_compile_features() and write_compiler_detection_header(). The problem with those is that they a

Jonathan Müller 74 Dec 26, 2022
[CMake] [BSD-2] CMake module to find ICU

FindICU.cmake A CMake module to find International Components for Unicode (ICU) Library Note that CMake, since its version 3.7.0, includes a FindICU m

julp 29 Nov 2, 2022
CMake project for BL602 RISC-V processor

bl602_cmake_base CMake project for BL602 RISC-V processor How to build NOTE : This project uses a pre-compiled version of the Buffalo SDK (bl_iot_sdk)

null 9 Jan 6, 2022
A CMake toolchain file for iOS, macOS, watchOS & tvOS C/C++/Obj-C++ development

A CMake toolchain file for iOS, macOS, watchOS & tvOS C/C++/Obj-C++ development

Alexander Widerberg 1.4k Jan 4, 2023