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 20th Edition

Release Date: 14th January 2025

This is part of the change history for the book Professional CMake: A Practical Guide. The 20th Edition has been updated for the CMake 3.31 release, which was a relatively minor update. This edition focuses mainly on correcting errata throughout the book.


Building Simple Targets chapter:

  • The third-last paragraph in the Linking Targets section contained a cross-reference that linked to the wrong content. The link to the Libraries chapter has been replaced with links to the Linking Libraries and Linking Static Libraries sections.

Basic Testing And Deployment chapter:

  • The Installing section contained an error in one of its examples. An install(DIRECTORY headers/ ...) example specified the wrong DESTINATION by including an extra trailing myproj. This has been fixed.
  • The Packaging section had a typo, specifying the incorrect variable name CPACK_GENERATORS instead of the correct CPACK_GENERATOR variable name. This has also been fixed.

Variables chapter:

  • In the CMake GUI Tools section, it incorrectly stated that a change in the value of a cache variable would result in that variable being highlighted at the end of the configure step. This is incorrect, only new variables are highlighted in red. The inaccurate text has been updated to make the behavior clear.

Using Subdirectories chapter:

  • The valid scopes from which project variables like <projectName>_SOURCE_DIR can be safely read has a complicated history in CMake. The wording in this chapter has been updated to make clear that such variables should only be read for a project defined in the same or a parent scope. The previous wording implied that they could be read from anywhere in the project, but this isn’t always safe. The wording now also no longer claims that these are cache variables (they might not be in all cases).

Modules chapter:

  • CMake 3.31 added a new CMAKE_REQUIRED_LINK_DIRECTORIES variable, which influences the various compilation test commands like the check_<lang>_source_compiles() family of commands.
  • The Checking Existence And Support chapter claimed that the check_<lang>_source_compiles() commands could return an error message in some situations. This is not the case, and the offending sentence has been removed.
  • The check_symbol_exists() and check_cxx_symbol_exists() commands historically required that the symbol names must always be a valid preprocessor symbol. That restriction was removed in CMake 3.16, but the book had not been updated accordingly. It has now been updated to account for this change.
  • The last example in the Checking Existence And Support chapter (pushing and popping check state) contained a typo. It set a variable named CMAKE_REQUIRED_DEFINES instead of the correct name CMAKE_REQUIRED_DEFINITIONS. This has been fixed.

Compiler And Linker Essentials chapter:

  • The Directory Properties And Commands section inaccurately described how flags that did not look like compile definitions are handled by the add_definitions() and remove_definitions() commands. The text wrongly stated that such flags are added to the COMPILE_OPTIONS directory property, but they are actually handled via an internal mechanism not exposed to the project. The offending text has been corrected.
  • In the example for the add_compile_options() command, the comment mentioned the wrong subdirectory in the first comment. It erroneously mentioned the "second" subdirectory, but it should have been "first". This has been corrected.

Advanced Linking chapter:

  • A new section Library Ordering And De-duplication was added. It discusses how CMake may reorder and de-duplicate the libraries on the linker command line, and it mentions the new LINK_LIBRARIES_STRATEGY target property added in CMake 3.31.

Custom Tasks chapter:

  • In CMake 3.31, the add_custom_command() command gained a new CODEGEN keyword. The Commands That Generate Files section was expanded and updated to account for this new keyword.

Working With Files chapter:

  • CMake 3.31 changed the default behavior when the CMAKE_TLS_VERIFY cache and environment variables are not defined, and it also changed the default minimum TLS version to 1.2. The text was updated to mention both changes.

Libraries chapter:

  • A brief paragraph was added to the end of the Linking Static Libraries section to mention that CMake may change the order and de-duplicate libraries on the linker command line.

Toolchains And Cross Compiling chapter:

  • The text and examples in the Using The NDK section have been updated to account for the Android NDK r27 release adding support for a larger 16KiB page size, and r28 changing the default to that new page size.

Apple Features chapter:

  • The Deployment Target section contained an error, mentioning an OSX_DEPLOYMENT_TARGET target property which doesn’t exist. Only the CMAKE_OSX_DEPLOYMENT_TARGET variable exists, and the wording was updated to more correctly explain its use. A similar error in the Recommended Practices section was also fixed.
  • The text of the Creating And Exporting Archives section contained a typo. It mentioned MyApp.archive instead of the MyApp.xcarchive name used in all the examples. This typo has been fixed.
  • An example in the Embedding Frameworks And Other Things section contained an error where it was meant to set the CMAKE_BUILD_WITH_INSTALL_RPATH variable to YES, but the value was erroneously omitted. This example has been updated to set the value as originally intended.

Build Performance chapter:

  • The Unity Builds section was updated to account for CMake 3.31 adding unity build support for CUDA.

Test Resources And Constraints chapter:

  • The Parallel Execution and Recommended Practices sections erroneously claimed that ctest supports a -l command line option, but the option name is actually --test-load. The Parallel Execution section has been reorganised to improve the logical flow, and this error has been corrected as part of that reorganisation. The discussion of the effectiveness of --test-load has also been updated to more accurately describe the problems with using it.
  • It was also previously claimed that parallel execution had to be enabled for the load limit (--test-load) to be honoured, but this is not the case. Even for serial execution, the load limit will be considered if the system is already busy with other processes. The offending claim has been removed.

Test Frameworks chapter:

  • The gtest_discover_tests() command gained a new DISCOVERY_EXTRA_ARGS keyword in CMake 3.31. The signature of that command has been updated in the GoogleTest section, but the new option is not discussed further.

Static Code Analysis chapter:

  • In the Settings subsection of the clang-tidy section, the small example showing how to override clang-tidy options in a subdirectory contained a typo. In the Checks line, it should have excluded the clang-analyzer-* checks, but it was missing a leading hyphen and was therefore adding them instead. This has been fixed.

Finding Things chapter:

  • The Finding Libraries section discusses how to prefer static libraries over shared during the search. The text and example used to highlight robustness problems with using NAMES to implement this was wrong, being based around the behavior when the NAMES_PER_DIR keyword is present, but not actually using that keyword in the example. The text and examples have been reworked and expanded to remove the error and to demonstrate the originally intended problem involving NAMES_PER_DIR.

Installing chapter:

  • The Whole Directories subsection of the Installing Files section contained an error in one of its examples. An install(DIRECTORY) command contained both the FILES_MATCHING and EXCLUDE keywords, but that would result in no files being installed. The FILES_MATCHING keyword should not have been there and has been removed.

Packaging chapter:

  • The Multiple Build Directories section contained some typos. It specified the wrong variable names CMAKE_COMPONENTS_ALL, CMAKE_COMPONENTS_XXX, and CMAKE_COMPONENTS_RUNTIME instead of the correct names CPACK_COMPONENTS_ALL, CPACK_COMPONENTS_XXX, and CPACK_COMPONENTS_RUNTIME. These have all been corrected.
  • The Multiple Build Directories section discusses the CPACK_INSTALL_CMAKE_PROJECTS variable. The “project name” part was previously described as “…only important for multi-configuration generators”. While that may have once been true, it is now only used exclusively for log output. The text has been updated accordingly.
  • The explanation of the third field of a CPACK_INSTALL_CMAKE_PROJECTS quadruple was both incomplete and lacking clarity. That field can be either a component name, or the name of a set of components, but the previous text conflated the two. The text and examples in Multiple Build Directories have been updated to clearly explain both ways of using this field.

Package Generators chapter:

  • CMake 3.31 brought back the change to make perMachine the default install scope for the WIX package generator (set by the CPACK_WIX_INSTALL_SCOPE variable), but this time subject to a new policy.
  • CMake 3.31 added a new CPACK_IFW_PACKAGE_PRODUCT_IMAGE_URLS variable.
  • Added a recommendation to the Inno Setup section to disable the licensing page during installation, preferring to show it when the installed application is run instead so that the installer can support scripted, unattended installs.

Presets chapter:

  • CMake 3.31 added presets schema version 10. This has been added to the corresponding version table in the High Level Structure section.
  • Presets schema 10 supports a new $comment field. A new Comments subsection was added to the Configure Presets section to show how to use it, along with workarounds for adding comments with earlier schema versions.
  • CMake 3.31 supports a slightly simpler command line for executing a workflow. The --preset option can be omitted, allowing the simpler and more intuitive command line: cmake --workflow presetName

Project Structure chapter:

  • The VS_DEBUGGER_ENVIRONMENT example in the Windows-specific Issues section was updated to use %PATH% instead of $ENV{PATH}. This is more consistent with the recommendation to use ENVIRONMENT_MODIFICATION for the non-Windows cases. It will modify the PATH environment variable at test time rather than completely replacing it with whatever the environment held during CMake configuration.

Working With Qt chapter:

  • A paragraph was added to the Recommended Practices section, highlighting that the I18N_TRANSLATED_LANGUAGES keyword should always be given in the call to qt_standard_project_setup() if the project supports translations.