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

Release Date: 18th July 2019

This is part of the change history for the book Professional CMake: A Practical Guide. The 4th Edition has been updated for the CMake 3.15.0 release and also contains some other minor improvements. The following lists the main changes in this edition.


General Presentation:

  • Text readability has been improved by using fully black text. Previous editions used a dark grey, which was not as clear.

Setting Up A Project chapter:

  • New for CMake 3.15, the CMAKE_GENERATOR environment variable can be used to specify a default generator.
  • New for CMake 3.15, multiple targets can be given for the cmake --target command line option.

Variables chapter:

  • CMake 3.15 expanded the set of supported message types for the message() command, adding NOTICE, VERBOSE, DEBUG and TRACE logging levels. The minimum log level can also be specified with the --loglevel command line option.
  • Added comments highlighting that string(LENGTH) counts bytes rather than characters.
  • Added mention of the list(PREPEND), list(POP_FRONT) and list(POP_BACK) subcommands new for CMake 3.15.

Flow Control chapter:

  • Clarified wording for how numbers are treated by the if() command.

Using Subdirectories chapter:

  • Added new Project-relative Variables section describing the set of variables defined by the project() command.
  • Added paragraph to the Recommended Practices section advising to avoid using CMAKE_SOURCE_DIR and CMAKE_BINARY_DIR and prefer the project-relative variables instead.

Functions And Macros chapter:

  • Fixed incorrect variable name for numbered arguments ARG# –> ARGV#, adjusted example to highlight that numbering starts from 0 and point out that accessing ARGVx with x >= ARGC is undefined behavior.
  • Added explanation and example for handling unprocessed arguments with _UNPARSED_ARGUMENTS when using cmake_parse_arguments().
  • New for CMake 3.15, when using cmake_parse_arguments(), the _KEYWORDS_MISSING_VALUES variable can be used to detect single or multi-value keywords that were not given any values.
  • Highlighted that functions receive a copy of all variables from the calling scope.
  • Added advice to the Recommended Practices section to prefer to pass information into functions and macros via arguments rather than relying on variables from the calling scope.

Properties chapter:

  • Clarified the difference between DEFINED and SET for the get_property() command.

Generator Expressions chapter:

  • Added a brief note that new generator expressions were added in CMake 3.15 for extracting the base name, prefix and suffix of target-related file names.
  • Made the wording a bit clearer regarding CMake 3.12 allowing object libraries to be linked directly instead of using $.

Compiler And Linker Essentials chapter:

  • Added a small example showing how to more robustly add language-specific compiler flags to targets.

Custom Tasks chapter:

  • CMake 3.15 added a new JOB_POOL option to the add_custom_command() and add_custom_target() commands.
  • Added more explicit comments that a target cannot be made to depend on an output of add_custom_command() from a different directory scope.
  • New for CMake 3.15, the execute_process() command now accepts a new COMMAND_ECHO option and has an associated CMAKE_EXECUTE_PROCESS_COMMAND_ECHO variable.
  • Fixed typo in example: add_program() –> add_executable().
  • Added extra comments for archiver.cmake example to highlight why having it as a separate file can be useful.
  • Added note to the Recommended Practices section for when using execute_process() may be appropriate.

Working With Files chapter:

  • CMake 3.15 added a new FOLLOW_SYMLINK_CHAIN option to the file(COPY) and file(INSTALL) subcommands.
  • Updated the file(COPY) example to use more appropriate permissions (world execute rather than world write for the whoami.sh file).

Toolchains And Cross Compiling chapter:

  • Added discussion of CMAKE_GENERATOR_PLATFORM and CMAKE_GENERATOR_TOOLSET and their associated -A and -T command line options, with examples for Visual Studio.
  • Added brief explanation of CMAKE_GENERATOR_INSTANCE and when it may be useful.

Apple Features chapter:

  • New for CMake 3.15, the CMAKE_FRAMEWORK variable is now used to initialize the FRAMEWORK target property.

Finding Things chapter:

  • New for CMake 3.15, the CMAKE_FIND_PACKAGE_PREFER_CONFIG variable can be used to change the search preference of find_package() to look for config package files before a find module.
  • CMake 3.15 introduced policy CMP0090 to make the default behavior of export(PACKAGE) not update the package registry. The new CMAKE_EXPORT_PACKAGE_REGISTRY variable can be used to re-enable it if required.
  • Added note that pkg_get_variable() would incorrectly ignore CMAKE_PREFIX_PATH with CMake 3.14 and earlier due to a bug (fixed in CMake 3.15.0).

Testing chapter:

  • CMake 3.15 allows CROSSCOMPILING_EMULATOR to hold a list rather than just a single value. It can now include arguments too, not just a single script or executable.

Installing chapter:

  • CMake 3.15 removed the problematic caching optimization in find_dependency() that sometimes caused package components to be handled incorrectly.
  • CMake 3.15 added a new cmake --install command line option to allow an install to be performed without invoking the build tool. It also has more flexibility and is easier to use than running the cmake_install.cmake script from the build directory.

Project Organization chapter:

  • Split up the Miscellaneous Project Features section into three new sections with more specific focus: Cleaning Files, Re-running CMake On File Changes and Injecting Files Into Projects.
  • CMake 3.15 added ADDITIONAL_CLEAN_FILES directory and target properties as more general replacements for the existing ADDITIONAL_MAKE_CLEAN_FILES directory property.
  • CMake 3.15 added new CMAKE_PROJECT_INCLUDE and CMAKE_PROJECT_INCLUDE_BEFORE variables for injecting content after or before any project() command.
  • Added a paragraph to the Recommended Practices section mentioning how CMAKE_PROJECT__INCLUDE can be used with continuous integration builds to mitigate problems with unwanted values in the CMake cache for incremental builds.