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

Release Date: 11th August 2020

This is part of the change history for the book Professional CMake: A Practical Guide. The 7th Edition has been updated for the CMake 3.18 release. It includes new, updated and reorganized material. Major highlights for this edition include significantly expanded coverage of command argument handling and a new chapter on debugging and diagnostics for running CMake. For the first time, the book is now also available in EPUB and MOBI formats, in addition to the usual PDF. The following lists the main changes in this edition.


The formats in which the book is available has been expanded to include PDF, EPUB and MOBI. The formats contain the same content with the following minor differences:

  • Some EPUB and MOBI code examples have slight differences (typically just formatting) to allow for better readability on devices with narrower widths.
  • The EPUB and MOBI formats do not have an index at the end of the book.

The PDF file size has also been significantly reduced by about 60% through additional post-processing.

Variables chapter:

  • Most of the section covering the message() command has been moved to its own new chapter (Debugging And Diagnostics). Only the essential points have been retained in the Variables chapter to avoid distracting the reader from the main focus.
  • Added a note that the ccmake tool is not part of the official CMake packages for Windows.
  • CMake added a new NATURAL sorting option for the list(SORT) command.
  • A new section Problems With Unbalanced Square Brackets was added to cover a less well-known aspect of CMake’s list handling behavior.

Flow Control chapter:

  • Correct a slightly inaccurate statement about what variables are defined for the IN ZIP_LISTS form of the foreach() command. Variables past the end of shorter lists are undefined, not set to empty.

Functions And Macros chapter:

This chapter was substantially reworked and expanded to better cover argument handling and other features new in CMake 3.18. The main changes were the following:

  • CMake 3.18 added a new cmake_language() command, which is now covered in a new section Other Ways Of Invoking CMake Code.
  • CMake 3.18 also added support for a number of CMAKE_CURRENT_FUNCTION* variables which can be used to provide information about the function currently being executed. This is covered in a new section Special Variables For Functions.
  • Added discussion of the PARSE_ARGV form of the cmake_parse_arguments() command. This form has been available since CMake 3.7 and provides improved robustness when parsing function arguments.
  • Added a note that the contents of <prefix>_UNPARSED_ARGUMENTS will have semicolons escaped when using the PARSE_ARGV form of the cmake_parse_arguments() function. Examples were updated to highlight how and why this can be useful.
  • More clearly explain how and whether variables are defined for valueless, single-value and multi-value keyword arguments.
  • Added a discussion and example of implementing multi-level keyword argument parsing.
  • Added a note regarding the limitation that cmake_parse_arguments() does not support repeated keywords except for certain multi-value argument parsing arrangements.
  • A new section Problems With Argument Handling was added. It covers some often poorly understood aspects of CMake’s command argument handling in detail. A number of important observations are presented, along with explanations of some common problems associated with argument parsing and forwarding (e.g. list flattening and empty arguments being dropped). Techniques for how to avoid or work around these problems are given. Some special cases relating to argument expansion are also discussed. The PARSE_ARGV form of cmake_parse_arguments() and the new cmake_language() command are key parts of this new section.

Properties chapter:

  • CMake 3.18 added the ability to specify a directory scope when calling one of the setter or getter property commands to operate on source file properties. Previously, only source properties from the current directory scope could be set or retrieved.

Generator Expressions chapter:

  • Removed a couple of stray values from the table that showed various boolean generator expressions and their results. Both erroneous values were for rows that generate an error rather than producing a value.
  • Slightly expanded the discussion of quoting as part of the $<JOIN:...> expression details. The text now also mentions how quoting is necessary to avoid semicolons causing unwanted argument splitting.
  • Added a cross-reference in the Recommended Practices section to the Debugging Generator Expressions section in a separate new chapter.

Modules chapter:

  • Moved the contents of the Useful Development Aids section to the new Debugging And Diagnostics chapter.
  • Slightly simplified the example for the CheckCSourceCompiles module.
  • CMake 3.18 added a new CheckLinkerFlag module.
  • Updated the Recommended Practices section to note that code checks often dominate the profiling results of a CMake run (profiling is a new feature in CMake 3.18).

Debugging And Diagnostics chapter:

This is a new chapter for the 7th Edition. Material relating to debugging and diagnostics was moved from a number of earlier chapters and collected here in this new chapter. A number of significant new sections have also been added:

  • CMake 3.16 and 3.17 added features for message indenting, message contexts and messages associated with performing checks. These significantly expand the versatility of the message() command and provide projects and users with more control over the log output CMake generates.
  • A new section was added to discuss and provide examples for how to debug generator expressions.
  • CMake 3.18 added new cmake command line options for profiling the CMake run itself. This can be used to gain insight into what commands and parts of the project are taking the most time during the configure stage.

Language Requirements chapter:

  • Removed the comment that “…for some compilers/linkers, [the <LANG>_EXTENSIONS] setting can change the standard library the target is linked with”.

Target Types chapter:

  • From CMake 3.18, it is now possible to create a (non-global) alias for a non-global imported target. For libraries, how such aliases compare to INTERFACE IMPORTED libraries is also discussed.

Custom Tasks chapter:

  • CMake 3.18 added new ECHO_OUTPUT_VARIABLE and ECHO_ERROR_VARIABLE options to the execute_process() command. These can be used to capture the output and error streams but still have them show up in the CMake output too.

Working With Files chapter:

  • CMake 3.18 added the file(CONFIGURE) subcommand. It can be used to perform a similar task as configure_file() except that the input comes from a string instead of a file.
  • CMake 3.18 extended the file(UPLOAD) subcommand to support the TLS_VERIFY and TLS_CAINFO options. Previously, these options were only available for file(DOWNLOAD).

Specifying Version Details chapter:

  • Added a note that symbol visibility may need to be considered if version functions are to be exposed as part of a shared library’s API.

Finding Things chapter:

  • CMake 3.18 added support for a REQUIRED option to the find_file(), find_path(), find_program() and find_library() commands. This makes them more consistent with find_package() which already supported a REQUIRED option.

Testing chapter:

  • CMake 3.18 added support for a new ctest --stop-on-failure option. This will end a test run immediately upon the first error encountered.
  • Added a note that CMake 3.8 and earlier considers skipped tests to be an error, but CMake 3.9 and later does not.
  • A new CTEST_RESOURCE_SPEC_FILE variable can be used with CMake 3.18 or later as an alternative way to specify the JSON file that defines the resources available to a ctest run.
  • The gtest_discover_tests() command gained a new DISCOVERY_MODE keyword in CMake 3.18. This can be used to control whether test discovery is performed at built time or test time (the latter can be important if cross-compiling). A new CMAKE_GTEST_DISCOVER_TESTS_DISCOVERY_MODE variable can be used to change the default behavior globally.

Packaging chapter:

  • CMake 3.18 added support for a new CPACK_NSIS_MANIFEST_DPI_AWARE variable. It can be used to make NSIS installers DPI-aware.

External Content chapter:

  • The FetchContent module gained support for the SOURCE_SUBDIR option in CMake 3.18. The option is given to FetchContent_Declare() and used by FetchContent_MakeAvailable(). The option works in a similar way to the same-named option already available for ExternalProject_Add().

Project Organization chapter:

  • CMake 3.18 extended the source_group() command to also allow forward slashes to be used as separators between nesting levels, not just backslashes.

Build Performance chapter:

  • The initial unity build support added in CMake 3.16 only allowed an automatic batching of source files based on number of files and the order in which they were added to the target. CMake 3.18 adds a new UNITY_BUILD_MODE target property which can be used to select between the existing automatic behavior and manual grouping. A new UNITY_GROUP source file property controls the unity group each source file belongs to in manual mode.

Working With Qt chapter:

  • Added a brief discussion of the qt5_add_big_resources() command.
  • Added a new section Transition To Qt 6, which discusses features added in Qt 5.15 to help projects prepare for Qt 6.