Release Date: 29th September 2022
This is part of the change history for the book Professional CMake: A Practical Guide. The 13th Edition has been updated for the CMake 3.24 release. This is by far the largest update yet. A number of new chapters have been added: Advanced Linking, Making Projects Consumable and Dependency Providers. The External Content chapter was also split into two, since the FetchContent material grew significantly and became its own separate chapter. A major new feature covered in this edition is the integration between find_package()
and the FetchContent
module. The material on Ccache has also been updated for the recently added support for the Visual Studio toolchain. As usual, a variety of smaller updates and clarifications have been made as well. Full details of the changes are given below.
Flow Control chapter:
- CMake 3.24 added a new
PATH_EQUAL
operator for theif()
command. It is similar toSTREQUAL
but handles repeated path separators. - Added an example for
if(IN_LIST)
and highlight that policyCMP0057
must be set toNEW
in order to use it.
Functions And Macros chapter:
- Added explanation for how to robustly forward arguments in a macro command where list flattening isn’t a concern. This will be relevant for some dependency provider implementations (a new feature in CMake 3.24).
Generator Expressions chapter:
- CMake 3.24 added new
$<PATH:...>
and$<PATH_EQUAL:...>
generator expressions. These are essentially the generator expression equivalents of thecmake_path()
sub-commands.
Debugging And Diagnostics chapter:
- CMake 3.24 gained support for enabling color diagnostics in the output of the build tool and compiler. This is controlled by a new
CMAKE_COLOR_DIAGNOSTICS
CMake variable and a corresponding environment variable of the same name. These replace the oldCMAKE_COLOR_MAKEFILE
variable which enabled colorised output for just themake
build tool. - The new
cmake --fresh
option can be used with CMake 3.24 or later to discard the cache from any previous run in the same build directory.
Compiler And Linker Essentials chapter:
- A new section on compiler option abstractions was added.
- One subsection covers turning compiler warnings into errors with the
COMPILE_WARNING_AS_ERROR
target property and its associatedCMAKE_COMPILE_WARNING_AS_ERROR
variable. These are new features in CMake 3.24. Later parts of the chapter were also updated to no longer use-Werror
in any examples. - Another subsection covers how to specify the Visual Studio runtime library with the
MSVC_RUNTIME_LIBRARY
target property and its associatedCMAKE_MSVC_RUNTIME_LIBRARY
variable. These have been supported since CMake 3.15.
- One subsection covers turning compiler warnings into errors with the
- The De-duplicating Options section previously made an incorrect statement that
LINKER:...
arguments could be de-duplicated. This is not correct, as expansion ofLINKER:...
items occurs after de-duplication. The text and examples have been updated accordingly. - The Advanced Linking Relationships section was moved out to its own separate Advanced Linking chapter.
- Added advice to the Recommended Practices section to avoid hard-coding turning compiler warnings into errors.
Advanced Linking chapter:
This is a new chapter for the 13th Edition.
- The Advanced Linking Relationships section of the previous chapter was moved to this chapter as the Require Targets For Linking section.
- A new section covers the new
$<LINK_GROUP:...>
and$<LINK_LIBRARY:...>
generator expressions added in CMake 3.24. These provide features like grouping libraries on the linker command line for rescanning for unresolved symbols, indicating that all symbols of a static library should be retained (i.e. the behavior of flags like/WHOLEARCHIVE
and--whole-archive
), robustly identifying an Apple framework and other Apple-specific linker capabilities. - Another new section covers the new
INTERFACE_LINK_LIBRARIES_DIRECT
target property added in CMake 3.24. It includes a detailed discussion of how to use that property to robustly implement the link seaming technique.
Language Requirements chapter:
- Fixed an example in the Detection And Use Of Optional Language Features section where
-D
prefixes were incorrectly included in arguments passed totarget_compile_definitions()
. Such prefixes are not stripped when part of a generator expression.
Custom Tasks chapter:
- Starting with CMake 3.24,
execute_process()
no longer sets theCC
andCXX
environment variables on the first run. That behavior existed with CMake 3.23 and earlier, but was undocumented. It could lead to different behavior between the first and subsequent runs, causing subtle and hard-to-trace issues if you didn’t know about that behavior. PolicyCMP0132
provides backward compatibility. The discussion at the end of the Configure Time Tasks section has been updated to highlight these changes, along with a workaround for when using CMake 3.23 or earlier. - An example in the Combining The Different Approaches section previously used
cmake_minimum_required(VERSION 3.0)
, but the example actually used features from CMake 3.17. The example has been updated to usecmake_minimum_required(VERSION 3.17)
instead.
Working With Files chapter:
- CMake 3.24 extended
file(DOWNLOAD)
to support downloading only part of a file.
Libraries chapter:
- The discussion in Mixing Static And Shared Libraries about using “whole archive” linker flags was updated to mention the
$<LINK_LIBRARY:WHOLE_ARCHIVE,...>
generator expression, available starting with CMake 3.24.
Apple Features chapter:
- CMake 3.24 added support for
*.xcconfig
files with the Xcode generator. A newCMAKE_XCODE_XCCONFIG
variable can be used to specify files to apply globally, while a newXCODE_XCCONFIG
target property supports files defining target-specific settings. These features may be useful for projects transitioning to CMake from an exclusively Xcode-only arrangement where*.xcconfig
files are commonly used. - The Linking Frameworks section was updated to mention the new
$<LINK_LIBRARY:FRAMEWORK,...>
generator expression available starting with CMake 3.24.
Finding Things chapter:
- Various places have been updated to cross-reference other chapters that discuss new features added in CMake 3.24 which integrate with
find_package()
. - All the
find_...()
commands gained newREGISTRY_VIEW
andNO_CMAKE_INSTALL_PREFIX
keywords in CMake 3.24, along with an associatedCMAKE_FIND_USE_INSTALL_PREFIX
variable. - CMake 3.24 added a new
GLOBAL
keyword forfind_package()
. When theGLOBAL
keyword is present, imported targets created as part of that call will have global visibility (they are normally created with visibility in only the current directory scope and below). ACMAKE_FIND_PACKAGE_TARGETS_GLOBAL
variable was also added as a way to change the default behavior. - A new search location for
find_package()
was added in CMake 3.24. This location is given by the new read-onlyCMAKE_FIND_PACKAGE_REDIRECTS_DIR
variable and it takes priority over all other search locations. It is used primarily for integration with theFetchContent
module (new functionality in CMake 3.24). Some brief notes about this integration were added here in this chapter, with cross-references to the detailed discussions in other chapters. - A note was added to highlight that
CMAKE_REQUIRE_FIND_PACKAGE_<packageName>
can break project logic. An example of a common scenario where this would occur is given. - The Recommended Practices section was updated to also mention
$<LINK_LIBRARY:FRAMEWORK,...>
as another way to link to something by name without breaking a developer’s ability to switch between device and simulator builds when targeting Apple platforms.
Testing chapter:
- CMake 3.24 added more granular control over the truncation of test output. A new
CTEST_CUSTOM_TEST_OUTPUT_TRUNCATION
variable controls which part of the output is truncated. A newctest --test-output-truncation
option provides equivalent control for non-dashboard runs using the--output-junit
option. - Examples using GoogleTest were updated to use the newer
GTest::gtest
andGTest::gtest_main
targets rather than the olderGTest::GTest
andGTest::Main
targets, which have been deprecated since CMake 3.20. A brief explanation of the situation was added to the TheGoogleTest
section.
Installing chapter:
- CMake 3.24 added a new feature for verifying that headers are self-contained, meaning they don’t rely on some other header having been included first. It builds on the file sets feature added in CMake 3.23. The new
CMAKE_VERIFY_INTERFACE_HEADER_SETS
variable can be set to true to enable the creation of targets that carry out these checks for appropriately defined file sets. It is intended to be a developer control, not something the project sets. For projects already using file sets to install their headers, it should be a very simple step for developers to enable these checks. The new capability is covered in the File Sets section of this chapter. - The
OUTPUT_NAME
target property is now discussed in the same place where theEXPORT_NAME
target property is introduced in the Installing Exports section. These two properties are related, so they should be discussed together.
Packaging chapter:
- CMake 3.24 changed the default value of
CPACK_DMG_SLA_USE_RESOURCE_FILE_LICENSE
, subject to the new policyCMP0133
. The behavior corresponding to the old default is no longer supported by recent Xcode releases. - The deprecated PackageMaker package generator was completely removed in CMake 3.24.
ExternalProject chapter:
The External Content chapter of the previous edition has been split up. The FetchContent section was moved out to its own dedicated chapter. The ExternalProject sections were revised and extensively restructured to provide a more logical flow, and the chapter has been renamed to ExternalProject in recognition of the narrower focus. The ExternalData section remains as part of the ExternalProject chapter.
- The
ExternalProject_Add()
command gained a newDOWNLOAD_EXTRACT_TIMESTAMP
option for use with URL archive downloads. It controls whether the timestamp of extracted files is updated to the time of extraction or set to the timestamp as contained in the archive. PolicyCMP0135
was also added, since the default behavior was changed in this regard.
FetchContent chapter:
This is a new chapter for the 13th Edition. The FetchContent section of the External Content chapter in the previous edition has been moved here, heavily revised and extended.
- A major new feature was added in CMake 3.24, providing integration between
find_package()
andFetchContent
. Dependencies requested via one method can now be transparently fulfilled by the other. Controls are provided for both the project and the developer. A substantial new section was added to this chapter covering the new features. - Discussion of the constraints around when
FetchContent
can be used for a particular dependency is now the subject of its own new chapter, Making Projects Consumable. The Restrictions section in the FetchContent chapter is now more brief, providing cross-references to the more comprehensive discussions in the other new chapter instead. - The discussion of the manual population pattern has mostly been removed. The chapter now focuses first and foremost on using
FetchContent_MakeAvailable()
, since it now has a much richer set of features than the manual population pattern can provide.
Making Projects Consumable chapter:
This is a new chapter for the 13th Edition. It provides clear and fairly comprehensive guidelines for what projects can do so that other projects can most easily consume them. The focus is on supporting the common methods consumers may use to bring the project in as a dependency, in particular as pre-built binary installs and building from source. These roughly correspond to the traditional find_package()
and FetchContent
scenarios. The integration between these two main methods in CMake 3.24 increases the importance of the points highlighted in this chapter. The material is combination of collecting individual points discussed elsewhere in the book, as well as some new recommendations. The guidelines are structured around a few key principles, with specific, actionable points discussed for each one.
Dependency Providers chapter:
This is another new chapter for the 13th Edition. CMake 3.24 added a significant new feature called dependency providers. These allow calls to find_package()
and FetchContent_MakeAvailable()
to be intercepted by a command the developer defines. That command can choose to fulfil the request in whatever way it prefers and indicate back to CMake whether it was successful, or whether to fall back to the built-in default implementation. The primary use case is for setting up package managers, but the chapter covers other use cases for this feature as well. An example showing how to use the feature to time dependency request calls is provided in an Appendix.
A new CMAKE_PROJECT_TOP_LEVEL_INCLUDES
variable is also introduced, which provides a well-defined injection point for one-time setup at the top of the project. This is also the only place a dependency provider can be set.
Project Organization chapter:
- The advice around how/where to bring dependencies into the build has changed from previous editions. With the new integration features between
find_package()
andFetchContent
, it is now more advantageous to bring dependencies into the build in the project’s top level scope rather than in a dedicated subdirectory. The focus on usingFetchContent_MakeAvailable()
rather than the manual population pattern removes the main motivation for using a separate directory scope. Examples have been updated accordingly and are now much simpler. Most of the discussions about the old manual population pattern have been removed. - A number of examples have been simplified to use the
PROJECT_IS_TOP_LEVEL
variable instead of comparingCMAKE_SOURCE_DIR
withCMAKE_CURRENT_SOURCE_DIR
. The minimum CMake version in the examples has been updated accordingly, where needed. - Variables used in examples to enable or disable testing have been renamed to be project specific, bringing them into line with recommendations in the new Making Projects Consumable chapter.
- The discussion of the
OUTPUT_NAME
target property was removed from the Target Outputs section, since that is now covered in the Installing Exports section of the Installing chapter. Since the material that remains all relates to the location of build outputs, the section has been renamed to Target Output Locations. - The Injecting Files Into Projects section was updated to mention to the new
CMAKE_PROJECT_TOP_LEVEL_INCLUDES
variable introduced in the Dependency Providers chapter. The discussion contrasts the different uses of the various injection variables supported by theproject()
command. Discussion of examples related to CI setup have been removed from this section, since that is now more appropriately done via presets or a script provided byCMAKE_PROJECT_TOP_LEVEL_INCLUDES
.
Build Performance chapter:
- A substantial new section on Build Parallelism was added. For each of the main CMake generator types, it covers how to enable parallel builds and what generator-specific controls are available. For Ninja, a detailed discussion of job pools is provided. For Visual Studio, the Multi-ToolTask scheduler is discussed, along with its relationship to the well-known
/MP
compiler option. CMake’s handling of the-parallelizeTargets
option for xcodebuild when using the Xcode generator is also discussed. The existing Optimizing Build Dependencies was also moved under this section. - Discussion of Ccache was expanded to cover the recently added support for the Visual Studio toolchain on Windows, including with the Visual Studio generators. Discussion about features in much older Ccache versions has been reduced and the material has been updated to focus more on recent Cccache releases. A complete, production-ready implementation supporting all the main CMake generators is provided as an Appendix.