Key Concepts

This chapter provides an introduction to CMake’s key concepts. As you start working with CMake, you will run into a variety of concepts such as targets, generators, and commands. Understanding these concepts will provide you with the working knowledge you need to create effective CMakeLists files. Many CMake objects such as targets, directories and source files have properties associated with them. A property is a key-value pair attached to a specific object. The most generic way to access properties is through the set_property and get_property commands. These commands allow you to set or get a property from any object in CMake that has properties. See the cmake-properties manual for a list of supported properties. From the command line a full list of properties supported in CMake can be obtained by running cmake with the --help-property-list option.

Targets

Probably the most important item is targets. Targets represent executables, libraries, and utilities built by CMake. Every add_library, add_executable, and add_custom_target command creates a target. For example, the following command will create a target named “foo” that is a static library, with foo1.c and foo2.c as source files.

add_library(foo STATIC foo1.c foo2.c)

The name “foo” is now available for use as a library name everywhere else in the project, and CMake will know how to expand the name into the library when needed. Libraries can be declared as a particular type such as STATIC, SHARED, MODULE, or left undeclared. STATIC indicates that the library must be built as a static library. Likewise, SHARED indicates it must be built as a shared library. MODULE indicates that the library must be created so that it can be dynamically-loaded into an executable. Module libraries are implemented as shared libraries on many platforms, but not all. Therefore, CMake does not allow other targets to link to modules. If none of these options are specified, it indicates that the library could be built as either shared or static. In that case, CMake uses the setting of the variable BUILD_SHARED_LIBS to determine if the library should be SHARED or STATIC. If it is not set, then CMake defaults to building static libraries.

Likewise, executables have some options. By default, an executable will be a traditional console application that has a main entry point. One may specify a WIN32 option to request a WinMain entry point on Windows systems, while retaining main on non-Windows systems.

In addition to storing their type, targets also keep track of general properties. These properties can be set and retrieved using the set_target_properties and get_target_property commands, or the more general set_property and get_property commands. One useful property is LINK_FLAGS, which is used to specify additional link flags for a specific target. Targets store a list of libraries that they link against, which are set using the target_link_libraries command. Names passed into this command can be libraries, full paths to libraries, or the name of a library from an add_library command. Targets also store the link directories to use when linking, and custom commands to execute after building.

Usage Requirements

CMake will also propagate “usage requirements” from linked library targets. Usage requirements affect compilation of sources in the <target>. They are specified by properties defined on linked targets.

For example, to specify include directories that are required when linking to a library you would can do the following:

add_library(foo foo.cxx)
target_include_directories(foo PUBLIC
                           "${CMAKE_CURRENT_BINARY_DIR}"
                           "${CMAKE_CURRENT_SOURCE_DIR}"
                           )

Now anything that links to the target foo will automatically have foo’s binary and source as include directories. The order of the include directories brought in through “usage requirements” will match the order of the targets in the target_link_libraries call.

For each library or executable CMake creates, it tracks of all the libraries on which that target depends using the target_link_libraries command. For example:

add_library(foo foo.cxx)
target_link_libraries(foo bar)

add_executable(foobar foobar.cxx)
target_link_libraries(foobar foo)

will link the libraries “foo” and “bar” into the executable “foobar” even though only “foo” was explicitly specified for it.

Specifying Optimized or Debug Libraries with a Target

On Windows platforms, users are often required to link debug libraries with debug libraries, and optimized libraries with optimized libraries. CMake helps satisfy this requirement with the target_link_libraries command, which accepts an optional flag labeled as debug or optimized. If a library is preceded with either debug or optimized, then that library will only be linked in with the appropriate configuration type. For example

add_executable(foo foo.c)
target_link_libraries(foo debug libdebug optimized libopt)

In this case, foo will be linked against libdebug if a debug build was selected, or against libopt if an optimized build was selected.

Object Libraries

Large projects often organize their source files into groups, perhaps in separate subdirectories, that each need different include directories and preprocessor definitions. For this use case CMake has developed the concept of Object Libraries.

An Object Library is a collection of source files compiled into an object file which is not linked into a library file or made into an archive. Instead other targets created by add_library or add_executable may reference the objects using an expression of the form $<TARGET_OBJECTS:name> as a source, where “name” is the target created by the add_library call. For example:

add_library(A OBJECT a.cpp)
add_library(B OBJECT b.cpp)
add_library(Combined $<TARGET_OBJECTS:A> $<TARGET_OBJECTS:B>)

will include A and B object files in a library called Combined. Object libraries may contain only sources (and headers) that compile to object files.

Source Files

The source file structure is in many ways similar to a target. It stores the filename, extension, and a number of general properties related to a source file. Like targets, you can set and get properties using set_source_files_properties and get_source_file_property, or the more generic versions.

Directories, Tests, and Properties

In addition to targets and source files, you may find yourself occasionally working with other objects such as directories and tests. Normally such interactions take the shape of setting or getting properties (e.g. set_directory_properties or set_tests_properties) from these objects.