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

Release Date: 4th January 2021

This is part of the change history for the book Professional CMake: A Practical Guide. The 8th Edition has been updated for the CMake 3.19 release. It includes new and updated material. Major highlights for this edition include support for Xcode’s new build system and Apple Silicon, along with a range of other linking-related improvements for Apple frameworks. A significant new feature called presets was added in CMake 3.19, as was another new feature allowing deferred execution of CMake code at the end of a directory scope. The following lists the main changes in this edition.

Variables chapter:

  • Improved the message labelling in the unbalanced square brackets example so that the sample output is clearer.
  • Mentioned briefly that the string() command now provides some JSON handling, but no detail beyond that is given in this edition.

Functions And Macros chapter:

  • CMake 3.19 added a new set of cmake_language(DEFER) subcommands. These can be used to define arbitrary CMake code to be executed at some later time.
  • Expanded the Special Cases For Argument Expansion subsection to account for the new cmake_language(DEFER) subcommands. Further sub-headings were also added to improve structure and navigation in this subsection.

Modules chapter:

  • Replace use of CMAKE_SOURCE_DIR with CMAKE_CURRENT_SOURCE_DIR in the CMAKE_MODULE_PATH example. This now follows the advice in other parts of the book regarding these variables.
  • CMake 3.19 added a new CheckSourceCompiles module, intended as a more generic replacement for the individual Check<LANG>SourceCompiles modules.
  • CMake 3.19 added a new CheckSourceRuns module, intended as a more generic replacement for the individual Check<LANG>SourceRuns modules.
  • CMake 3.19 added a new CheckCompilerFlag module, intended as a more generic replacement for the individual Check<LANG>CompilerFlag modules.

Debugging And Diagnostics chapter:

  • Clarified the descriptions of the NOTICE and STATUS log levels to make it clearer which one is the default when no log level is specified. A corresponding comment in the Recommended Practices section was also updated to remove an ambiguity in what a default log level meant.
  • Added reasoning for why one should generally prefer STATUS over NOTICE for informational messages.

Build Type chapter:

  • Added a note that when using Visual Studio compilers with single configuration generators (e.g. Ninja or NMake Makefiles), the default build type is Debug rather than an empty string.

Compiler And Linker Essentials chapter:

  • Added comments highlighting which target properties relating to compiler and linker options are subject to automatic de-duplication by CMake.
  • Added a new De-duplicating Options section. It presents scenarios where de-duplication needs to be prevented and shows how to use the SHELL: prefix to achieve that.
  • Earlier editions listed common mistakes made with variables under bold headings. These were promoted to proper sub-subheadings in this edition so that they show up in the table of contents and improve ease of navigation.

Target Types chapter:

  • A brief note about BUILD_SHARED_LIBS was added to the Libraries section to reiterate its use to select between STATIC and SHARED libraries when no library type is specified.
  • Subsections were added to the Libraries section to make finding information about some of the less common library types more discoverable.
  • CMake 3.19 added the ability to add private sources to interface libraries. Material has been added which highlights the restrictions this removes, using header-only libraries as a use case.
  • Made the note about propagation of an object library’s own link dependencies more prominent (it is not safe to rely on before CMake 3.14).
  • Fixed a wrong reference in the library alias example about linking to namespaced names. The reference was moved to a callout and is now an actual link to the Finding Things chapter.

Custom Tasks chapter:

  • CMake 3.19 relaxed some of the automatic dependency creation around some $<TARGET_...> generator expressions when they were used in custom commands. This is protected by the new policy CMP0112.
  • The execute_process() command gained a new COMMAND_ERROR_IS_FATAL keyword in CMake 3.19. This can remove the need to manually check the result of such calls, thereby making the code much more concise. The material added to the book also highlights that this new feature initially had some overlooked error cases in the 3.19.0 release, but that these were fixed in CMake 3.19.2.

Working With Files chapter:

  • CMake 3.19 added the file(REAL_PATH) subcommand. Material has been added about this, including a discussion about the inconsistencies it brings compared to the existing get_filename_component() command.
  • CMake 3.19 added the NO_SOURCE_PERMISSIONS keyword to the configure_file() command.
  • CMake 3.19 added the TARGET keyword to the file(GENERATE) subcommand. It can be used to provide a target for the evaluation of generator expressions that require a target for evaluation, such as $<TARGET_PROPERTY:...>.
  • CMake 3.19 added the file(CHMOD) and file(CHMOD_RECURSE) subcommands for manipulating file and directory permissions.
  • CMake 3.19 now allows the file name given to file(DOWNLOAD) to be omitted. This will discard the downloaded file, which can be useful if you just want to check that it can be downloaded without actually saving it anywhere.

Toolchains And Cross Compiling chapter:

  • CMake 3.19 now allows CMAKE_<LANG>_COMPILER to be a list rather than just a single executable. Mandatory arguments can now be included in the list.
  • Mentioned that CMake 3.19 now allows the Android NDK to be used with the Visual Studio generator.

Apple Features chapter:

CMake 3.19 included a significant amount of work for Apple platforms. Much of this is not directly user-visible, but the features enabled by that work are significant.

  • CMake 3.19 now supports Xcode’s new build system, but only for Xcode 12 or later. The new build system is used by default when using Xcode 12, so this change is mostly transparent to the developer.
  • Support for Xcode’s new build system in turn allowed support for Apple Silicon to be added. CMake 3.19.2 and Xcode 12.2 should be considered the minimum versions for targeting Apple Silicon, which is noted in the updated material in the book.
  • Updated the Universal Binaries section and added a new Intel And Apple Silicon Binaries subsection to it, explaining how to create universal binaries for macOS. This includes comments regarding how CMake itself being a universal binary may also affect the build.
  • Added a note to the Combined Device And Simulator Binaries section regarding an extra step that may be needed if building iOS universal binaries on an Apple Silicon host.
  • Updated the advice in the Compiler Test Workarounds subsection to note that CMAKE_XCODE_ATTRIBUTE_CODE_SIGNING_ALLOWED no longer has to be manually set in try_compile() calls as of CMake 3.18.2.
  • The Linking And Embedding Frameworks section was split into two separate sections, each covering one of these areas. The Linking Frameworks section was expanded to cover changes in behavior with CMake 3.19 which make linking frameworks work more seamlessly by default, especially for archive operations. The existing content of this section was also reworked in places to make it more complete and to improve the discussion flow. CMake 3.19’s new functionality relating to using Xcode’s Link Binaries With Libraries build phase is also discussed.
  • The Limitations section was also updated to account for the improved framework linking with CMake 3.19.
  • Minor changes were made to the Recommended Practices section to account for the changes mentioned above.
  • Added a note that the names for an Xcode project’s build settings can also be shown using the Editor > Show Setting Names menu item.
  • Fixed an example in the Deployment Target section where CMAKE_OSX_DEPLOYMENT_TARGET was erroneously being created as a regular variable instead of a cache variable.
  • Fixed a typo in an iOS example where Apple Developer was used for the code signing identity instead of Apple Development.

Finding Things chapter:

  • CMake 3.19 now supports specifying version ranges in the version requirements given to find_package().

Testing chapter:

  • CMake 3.19 allows test names to contain spaces, quotes and other special characters. The book notes the history of this support, as it was originally added in 3.18, but then withdrawn after it was found to break existing projects. CMake 3.19 reintroduced it again, this time with a policy.
  • Sections of the book relating to CDash were updated to use the terminology groups rather than tracks. CMake 3.16 deprecated the --track option in favor of a new --group option.
  • CMake 3.19 added support for a new MemCheck type, Cuda Sanitizer.

Installing chapter:

  • Updated the Config Files For CMake Projects section to account for CMake 3.19’s new support for version ranges in calls to find_package(). The set of variables provided to package version files has been expanded considerably.

External Content chapter:

  • CMake 3.19 added the INDEPENDENT keyword to the ExternalProject_Add_Step() command as part of the work to support Xcode’s new build system. A discussion of what the keyword does and why one might want to use it is provided.
  • Related to the preceding point, CMake 3.19 deprecated the NO_DEPENDS keyword to ExternalProject_Add_StepTargets().
  • The CompanyXToolchains example for FetchContent was updated to use FetchContent_MakeAvailable(), making it more concise.

Project Organization chapter:

  • CMake 3.19 added a significant new feature called presets. These provide a convenient new way of configuring the first CMake run in a build directory with prepared settings. These are useful in a number of different scenarios. A new Presets section has been added to cover the most important aspects of this new functionality.
  • The Recommended Practices section was updated to mention the VS_DEBUGGER_ENVIRONMENT target property as a better way of improving the debugger experience within the Visual Studio IDE. Previously, it mentioned the older VS_USER_PROPS target property, but this was not updated in an earlier edition of the book when discussion of the VS_DEBUGGER_ENVIRONMENT property was introduced elsewhere.

Build Performance chapter:

  • Added a note to the Alternative Linkers section regarding a bug in lld which may affect developers using the Android NDK.
  • CMake 3.19 added a new ability to relax dependencies of static and object libraries in certain situations. This can potentially reduce rebuilds or improve build parallelism. A new Optimizing Build Dependencies section was added to cover this new functionality.

Working With Qt chapter:

  • Some minor updates were added to this chapter to reflect that Qt 6.0 has now been officially released. Since the CMake support for Qt 6.0 is still considered to be in Tech Preview, this chapter still largely focuses on Qt 5.
  • Added a note about a change in behavior since CMake 3.17.0 (which has subsequently been reverted in CMake 3.19.2) which had an adverse effect on projects using the qt5_create_translation() command conditionally based on a CMake cache variable. The change resulted in .ts files being deleted in certain situations. The book provides exactly this scenario as an example, so a note has been added highlighting the specific circumstances where the problem may arise.