Professional CMake:

A Practical Guide

Learn to use CMake effectively with practical advice from a CMake co-maintainer. You can also have the author work directly with your team!

Professional CMake: A Practical Guide 9th Edition

Release Date: 26th April 2021

This is part of the change history for the book Professional CMake: A Practical Guide. The 9th Edition has been updated for the CMake 3.20 release. The more substantial changes for this edition include support for embedding frameworks with the Xcode generator, a new cmake_path() command for general path manipulation, extension of the presets feature to support build and test presets, and removal of material related to the now deprecated TestBigEndian and WriteCompilerDetectionHeader modules. A collection of smaller updates and clarifications have also been made. The main changes in this edition are listed below.

NOTE: This is the last edition for which the MOBI format will be provided. The kindlegen tool used to create it thus far was withdrawn from public distribution last year and Amazon is officially dropping support for creating MOBI files altogether in June 2021. The EPUB format will continue to be made available.


Flow Control chapter:

  • The discussion of how if(IS_NEWER_THAN) can be misleading has been expanded and examples have been added.

Modules chapter:

  • CMake 3.20 deprecated the TestBigEndian module. The corresponding Endianness section has been removed from this chapter and the Recommended Practices section was updated to mention the new CMAKE_<LANG>_BYTE_ORDER variable that replaces it.

Compiler And Linker Essentials chapter:

  • CMake 3.20 added a new AFTER keyword to the target_include_directories() command (mostly for symmetry, since AFTER is already the default behavior).

Language Requirements chapter:

  • CMake 3.20 added support for specifying C++23 by setting CMAKE_CXX_STANDARD to 23.
  • Added more precise details for which CMake releases added support for which CUDA versions.
  • CMake 3.20 deprecated the WriteCompilerDetectionHeader module. The corresponding discussion of that module in the Detection And Use Of Optional Language Features section has been removed and replaced by a brief note about the deprecation. The Recommended Practices section was also updated to advise more strongly not to use the module.

Custom Tasks chapter:

  • CMake 3.20 added limited support for generator expressions in the OUTPUT and BYPRODUCT arguments of add_custom_command() and add_custom_target().
  • CMake 3.20 expanded depfile support in add_custom_command() to include Makefile generators (previously only Ninja generators were supported). A new associated policy CMP0116 was also added, but it leads to noisy warnings in potentially harmless situations. An explanation of the cause of those warnings and how to avoid them has been added.

Working With Files chapter:

  • CMake 3.20 added a new cmake_path() command. The Manipulating Paths section has been updated to introduce the new command and present some common uses. Its relationship to the existing get_filename_component() and file() sub-commands is also highlighted.
  • The Recommended Practices section now recommends preferring the new cmake_path() command. It also highlights some subtle differences in behavior compared to the if(IS_ABSOLUTE) command.
  • CMake 3.20 expanded the control of permissions for configure_file() and file(GENERATE) such that they both now both support the same NO_PERMISSIONS, USE_SOURCE_PERMISSIONS and FILE_PERMISSIONS keywords as the file(COPY) sub-command.

Toolchains And Cross Compiling chapter:

  • CMake 3.20 added hooks and fixes needed for the Android NDK to drive CMake’s built-in Android support reliably, with corresponding updates expected in the upcoming NDK r23 release. The Android note in the Examples section regarding the status of this work and corresponding advice in the Recommended Practices section have been updated accordingly, but the rest of the content still largely reflects the old approach.

Apple Features chapter:

  • Discussion of the XCODE_LINK_BUILD_PHASE_MODE target property in the Linking Frameworks section was expanded to explain the supported options and their effect.
  • A long-standing deficiency in CMake’s install name handling would leave iOS apps using embedded shared libraries unable to run. That bug was fixed in CMake 3.20.1. A note has been added to the end of the Linking Frameworks section to draw attention to that bug and it being fixed.
  • CMake 3.20 added direct support for embedding frameworks into app bundles when using the Xcode generator. The Embedding Frameworks section was updated to cover the new capabilities. The old approach is still presented as a workaround for those who need to remain on an older CMake version for the time being. The Limitations and Recommended Practices sections have also been updated in recognition of the new features.
  • Wording around the CMAKE_APPLE_SILICON_PROCESSOR variable has been tightened to make it clear that it has to be a cache variable, not just any variable.

Testing chapter:

  • In CMake 3.20, the ctest command gained a new --test-dir option for specifying the directory for which tests should be run (instead of assuming the current directory).
  • The Defining And Executing A Simple Test section had been incorrectly stating that ctest supported -VVV as an “extra verbose” command line option. The erroneous text has been corrected.

Installing chapter:

  • CMake 3.20 added support for directly rewriting RPATH details for the XCOFF binary format on AIX.
  • A note was added to the Apple-specific Targets sub-section to draw attention to the long-standing bug in CMake’s install name handling, which was fixed in CMake 3.20.1 (this is the more detailed description of the same problem noted briefly in the Apple Features chapter).
  • Added a brief comment in the Apple-specific Targets sub-section to state the equivalent RPATH target property values for iOS when describing the relationship between executables and their embedded frameworks. Previously, only the values for macOS were given.
  • Updated the RPATH example for an app bundle with embedded frameworks to link directly to its frameworks instead of using the form -framework XXX. This simplification takes advantage of improvements made in CMake 3.19.

Packaging chapter:

  • Added brief note that cpack_ifw_configure_component() and cpack_ifw_configure_component_group() accept DEPENDENCIES as a synonym for DEPENDS.
  • Added discussion explaining how to set a version requirement on a DEPENDS value passed to cpack_ifw_configure_component().
  • Updated comments about QtIFW to note that it now supports unattended command-line installs since QtIFW 4.0.
  • CMake 3.20 added support for modifying the branding text in NSIS installers. A brief comment was added to mention the new variables used to control this behavior.
  • CMake 3.20 expanded the configuration variables supported by the NuGet installer. The text was updated to briefly mention the type of capabilities that were added.

External Content chapter:

  • Corrected an existing discussion to make clear that when using ExternalProject_Add(), if the requested GIT_TAG was an actual tag and was already checked out, the command would not fetch from the remote to check if the tag had moved.
  • Fixed typo where ExternalProject_Add_Step() was incorrectly written as External_Project_Add_Step().

Project Organization chapter:

  • CMake 3.20 now allows target_sources() to be used with custom targets. The Target Sources sub-section has been updated accordingly.
  • CMake 3.20 extended the existing configure presets to support build and test presets as well. The Presets section has been updated to account for the new capabilities, generalise some of the discussions and provide an example for each new type of preset.

Build Performance chapter:

  • CMake 3.20 added a new UNITY_BUILD_UNIQUE_ID target property. A brief note was added to mention its intended use to raise awareness, but the added text advises to prefer to rework the code to avoid the need for it.

Working With Qt chapter:

  • Updated the note regarding back-porting of the cleandead fix in CMake 3.19.2 for a Ninja-related bug. The fix was ultimately not back-ported to CMake 3.17, only to 3.18.