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_EQUALoperator for the
if()command. It is similar to
STREQUALbut handles repeated path separators.
- Added an example for
if(IN_LIST)and highlight that policy
CMP0057must be set to
NEWin 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_EQUAL:...>generator expressions. These are essentially the generator expression equivalents of the
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_DIAGNOSTICSCMake variable and a corresponding environment variable of the same name. These replace the old
CMAKE_COLOR_MAKEFILEvariable which enabled colorised output for just the
- The new
cmake --freshoption 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_ERRORtarget property and its associated
CMAKE_COMPILE_WARNING_AS_ERRORvariable. These are new features in CMake 3.24. Later parts of the chapter were also updated to no longer use
-Werrorin any examples.
- Another subsection covers how to specify the Visual Studio runtime library with the
MSVC_RUNTIME_LIBRARYtarget property and its associated
CMAKE_MSVC_RUNTIME_LIBRARYvariable. 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 of
LINKER:...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_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
--whole-archive), robustly identifying an Apple framework and other Apple-specific linker capabilities.
- Another new section covers the new
INTERFACE_LINK_LIBRARIES_DIRECTtarget 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
-Dprefixes were incorrectly included in arguments passed to
target_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 the
CXXenvironment 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. Policy
CMP0132provides 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 use
Working With Files chapter:
- CMake 3.24 extended
file(DOWNLOAD)to support downloading only part of a file.
- 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
*.xcconfigfiles with the Xcode generator. A new
CMAKE_XCODE_XCCONFIGvariable can be used to specify files to apply globally, while a new
XCODE_XCCONFIGtarget property supports files defining target-specific settings. These features may be useful for projects transitioning to CMake from an exclusively Xcode-only arrangement where
*.xcconfigfiles 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
- All the
find_...()commands gained new
NO_CMAKE_INSTALL_PREFIXkeywords in CMake 3.24, along with an associated
- CMake 3.24 added a new
find_package(). When the
GLOBALkeyword 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). A
CMAKE_FIND_PACKAGE_TARGETS_GLOBALvariable 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-only
CMAKE_FIND_PACKAGE_REDIRECTS_DIRvariable and it takes priority over all other search locations. It is used primarily for integration with the
FetchContentmodule (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.
- CMake 3.24 added more granular control over the truncation of test output. A new
CTEST_CUSTOM_TEST_OUTPUT_TRUNCATIONvariable controls which part of the output is truncated. A new
ctest --test-output-truncationoption provides equivalent control for non-dashboard runs using the
- Examples using GoogleTest were updated to use the newer
GTest::gtest_maintargets rather than the older
GTest::Maintargets, which have been deprecated since CMake 3.20. A brief explanation of the situation was added to the The
- 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_SETSvariable 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.
OUTPUT_NAMEtarget property is now discussed in the same place where the
EXPORT_NAMEtarget property is introduced in the Installing Exports section. These two properties are related, so they should be discussed together.
- CMake 3.24 changed the default value of
CPACK_DMG_SLA_USE_RESOURCE_FILE_LICENSE, subject to the new policy
CMP0133. 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.
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.
ExternalProject_Add()command gained a new
DOWNLOAD_EXTRACT_TIMESTAMPoption 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. Policy
CMP0135was also added, since the default behavior was changed in this regard.
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
FetchContent. 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
FetchContentcan 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
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
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.
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
FetchContent, 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 using
FetchContent_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_LEVELvariable instead of comparing
CMAKE_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_NAMEtarget 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_INCLUDESvariable introduced in the Dependency Providers chapter. The discussion contrasts the different uses of the various injection variables supported by the
project()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 by
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
/MPcompiler option. CMake’s handling of the
-parallelizeTargetsoption 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.