My CMake Cheat Sheet (Updated Regularly)

Minimal Project

cmake_minimum_required(VERSION 3.2)
add_executable(myExe main.cpp)

Comments are # python style.


Executables are added with add_executable (see above).

Libraries with

add_library(targetName [STATIC | SHARED | MODULE]
  source1 [source2 ...]


Specifies a static library or archive. On Windows, the default library name would be targetName.lib, while on Unix-like platforms, it would typically be libtargetName.a.


Specifies a shared or dynamically linked library. On Windows, the default library name would be targetName.dll, on Apple platforms it would be libtargetName.dylib and on other Unix-like platforms it would typically be On Apple platforms, shared libraries can also be marked as frameworks, a topic covered in Section 22.3, “Frameworks”.

MODULE Specifies a library that is somewhat like a shared library, but is intended to be loaded dynamically at run-time rather than being linked directly to a library or executable. These are 16 typically plugins or optional components the user may choose to be loaded or not. On Windows platforms, no import library is created for the DLL.

Linking Targets

  <PRIVATE|PUBLIC|INTERFACE> item1 [item2 ...]
  [<PRIVATE|PUBLIC|INTERFACE> item3 [item4 ...]]


Private dependencies specify that library A uses library B in its own internal implementation. Anything else that links to library A doesn’t need to know about B because it is an internal implementation detail of A.


Public dependencies specify that not only does library A use library B internally, it also uses B in its interface. This means that A cannot be used without B, so anything that uses A will also have a direct dependency on B. An example of this would be a function defined in library A which has at least one parameter of a type defined and implemented in library B, so code cannot call the function from A without providing a parameter whose type comes from B.


Interface dependencies specify that in order to use library A, parts of library B must also be used. This differs from a public dependency in that library A doesn’t require B internally, it only uses B in its interface. An example of where this is useful is when working with library targets defined using the INTERFACE form of add_library(), such as when using a target to represent a header-only library’s dependencies.


Syntax for declaring a variables:

set(varName value... [PARENT_SCOPE])

varName is case sensitive. Values are all strings, optionally quoted (like when they contain spaces). Lists can be defined by separating with spaces or ;:

set(myVar a b c) # myVar = "a;b;c"
set(myVar a;b;c) # myVar = "a;b;c"
set(myVar "a b c") # myVar = "a b c"
set(myVar a b;c) # myVar = "a;b;c"
set(myVar a "b c") # myVar = "a;b c

To refer, use ${varName}.


Refer using syntax $ENV{varName}. Set using set(ENV{PATH} "/opt/my_dir").




Common operations (executed during configure stage):

file(RENAME source destination)
file(REMOVE files...)
file(REMOVE_RECURSE filesOrDirs...)
file(MAKE_DIRECTORY dirs...)


file(GLOB outVar
  [LIST_DIRECTORIES true|false]
  [RELATIVE path]
  [CONFIGURE_DEPENDS] # Requires CMake 3.12 or later


file(GLOB_RECURSE outVar
  [LIST_DIRECTORIES true|false]
  [RELATIVE path]
  [CONFIGURE_DEPENDS] # Requires CMake 3.12 or later

The difference between two above is recursive and non-recursive. Normal wildcards (*, ?) are supported.

CONFIGURE_DEPENDS forces list on every build which may be a performance penalty. It also doesn’t work with all generators.

[ more ]



message([mode] msg1 [msg2]...) can be used to display diagnostic messages in cmake console. [mode] is like log level i.e. STATUS, WARNING and is optional.


Link statically to msvc runtime (note that it requires at least CMake 3.15):

cmake_minimum_required (VERSION 3.15)
set_property(TARGET project PROPERTY
  MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Debug>:Debug>")

Have a question⁉ Contact me.