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

Release Date: 24th January 2024

This is part of the change history for the book Professional CMake: A Practical Guide. The 17th Edition has been updated for the CMake 3.28 release. The main highlights for this edition are support for C++20 modules and using XCFrameworks. Motivated by stronger requirements resulting from C++20 modules, the advice in the Language Requirements chapter has also been substantially updated. The changes apply to most projects, not just those using C++20 modules, so it is recommended that all developers review the updated advice in that chapter.

This edition also continues the structural improvements begun in the 16th Edition. File sets are becoming more important in CMake, so relevant details are now covered in earlier chapters instead of most of the material being delayed to the Installing chapter.

Full details of the changes are given below.


Properties chapter:

  • CMake 3.28 made it possible to specify the directory in which to find the test whose properties are being set or queried.
  • The previous Other Property Types section was split up into dedicated Test Properties and Installed File Properties sections.
  • Fixed a test property example which used the wrong argument order for get_test_property(). This example was previously in the Other Property Types section, and is now in the Test Properties section.

Modules chapter:

  • Fixed a wrong cross-reference to the Packaging chapter, which previously linked to the Packaging section in the Getting Started Guide by mistake.

Compiler And Linker Essentials chapter:

  • Added a new File Sets section. This mostly contains material that was previously found in the File Sets section of the Installing chapter, but it has also been updated to mention the new CXX_MODULES file set type for C++20 modules. The new section covers important information much earlier in the book, reflecting the increasingly fundamental nature of file sets in CMake.
  • Added a note early in the Header Search Paths section to highlight that file sets are now a better way to handle header search paths than raw calls to target_include_directories().
  • Slightly reordered some of the paragraphs in the Header Search Paths section to improve the logical flow.
  • Improved the explanation in Header Search Paths regarding the interaction of relative and absolute paths with generator expressions.
  • Added a paragraph to the Recommended Practices section recommending that all headers owned by a target be put into file sets.
  • Replaced all uses of Foo with better names throughout the chapter.
  • Fixed a wrong cross-reference to the Packaging chapter, which previously linked to the Packaging section in the Getting Started Guide by mistake.

Language Requirements chapter:

This chapter received a fairly significant overhaul. Some important recommendations affecting widely used patterns have been changed to better account for requirements of parent projects, and to support new constraints associated with C++20 modules.

  • The recommended way to set the CMAKE_<LANG>_STANDARD and CMAKE_<LANG>_EXTENSIONS variables has been updated. The new recommendations take into account the scenario where a parent project may want to override what a project would normally set, such as when using FetchContent. The need to use a consistent language standard and other compiler settings throughout the build has also become much more important with C++20 modules, and parent projects may need to enforce new constraints related to that.
  • Setting The Language Standard Directly now recommends not setting the <LANG>_STANDARD target property directly, instead letting it be controlled by CMAKE_<LANG>_STANDARD so that parent projects can override it.
  • The discussion of individual compile features has been removed from the Setting The Language Standard By Feature Requirements section. These individual compile features have little benefit with actively used compilers today. Projects should use the meta features like cpp_std_11 for the relevant language standard instead.
  • A new Requirements For C++20 Modules section was added to discuss new language requirements related to the C++20 module support added in CMake 3.28. This section covers the essential things needed to build a project that defines and uses its own C++20 modules. Later chapters deal with other important aspects of C++20 modules.
  • The Recommended Practices section was updated to reflect the new recommendations around CMAKE_<LANG>_STANDARD and CMAKE_<LANG>_EXTENSIONS, and the new C++20 modules support. Previous recommendations around detailed compile features has been removed, being replaced by a recommendation to not use them and instead use the language standard meta feature.

Target Types chapter:

  • The Imported Libraries section was updated to explain the CMake 3.28 changes affecting imported libraries with improved support for Apple frameworks, new support for Apple XCFrameworks, and expanded support for stub or import libraries for a number of platforms (at least Apple, Linux and AIX).

Custom Tasks chapter:

  • CMake 3.28 added support for a new JOBY_SERVER_AWARE option to add_custom_command() and add_custom_target().
  • The Commands That Generate Files section was expanded to explain new behavior in CMake 3.28 which affects how generated files are treated with regard to dependencies between targets. This is an important change, as it is also affected by whether or not a target uses file sets, and the behavior change does not trigger a policy warning while the project relies on the OLD policy setting.

Specifying Version Details chapter:

  • Fixed a wrong cross-reference to the Packaging chapter, which previously linked to the Packaging section in the Getting Started Guide by mistake.

Libraries chapter:

  • A new Additional Complications With C++20 Modules subsection was added to the Symbol Visibility section. CMake 3.28 added support for C++20 modules, but the symbol visibility aspects of that are poorly understood and are rarely mentioned in documentation. This new section highlights some common misconceptions about C++20 modules, and it provides a simple but complete example showing the important symbol visibility aspects of producing a shared library that exports a C++20 module.

Toolchains And Cross Compiling chapter:

  • Added mention of visionOS in a few places where Apple platforms are listed (new support in CMake 3.28).
  • Fixed example command lines in the Tool Selection section to use the correct name for the Visual Studio 16 2019 generator.
  • Minor update to the example in GCC With 32-bit Target On 64-bit Host to use STATUS with the call to message().

Apple Features chapter:

  • CMake 3.28 added support for visionOS. Various parts of this chapter have been updated to mention visionOS and XROS where relevant, but apart from naming the newly supported platform, no other explanations were needed.
  • A new Other Helpful Build Settings section was added, which discusses the CLANG_ENABLE_OBJC_ARC, CLANG_ENABLE_OBJC_WEAK, and CLANG_ENABLE_MODULES Xcode settings. The defaults for these in the CMake-generated file differ from the defaults in an Xcode-generated file. This section highlights that and explains why you may want to explicitly set them, along with the directly related clang module verifier.
  • A new XCFrameworks section was added. CMake 3.28 gained support for consuming XCFrameworks, but not producing one. The new section explains how to use that new support, and also provides some minimal details for creating an XCFramework.
  • The Universal Binaries section was updated to account for XCFrameworks. Apple now discourages putting device and simulator slices in the one universal binary. They now recommend XCFrameworks for that.
  • Linking Frameworks was updated to mention auto-linking of frameworks, which Other Helpful Build Settings now covers.
  • CMake 3.28 gained support for embedding resources, and extended the framework embedding support to XCFrameworks. The Embedding Frameworks, Plugins And Extensions section was renamed to Embedding Frameworks And Other Things, and updated to mention the new embedding resources and XCFramework embedding support. A note was also added about an existing CMake bug that prevents listing an imported framework target in XCODE_EMBED_FRAMEWORKS.
  • The IOS_INSTALL_COMBINED target property and its associated CMAKE_IOS_INSTALL_COMBINED variable are deprecated as of CMake 3.28. They don’t work at all with Xcode 15 or later. The Combined Device And Simulator Binaries subsection has been updated to note the deprecation, and the explanation of how to use the feature has been removed.
  • The -destination option for xcodebuild is now mentioned as an alternative to specifying -arch in a number of places.
  • The Recommended Practices section now recommends creating XCFrameworks instead of using the deprecated IOS_INSTALL_COMBINED feature when producing a framework that supports multiple platforms.

Build Performance chapter:

  • The CMake bug preventing the OPTIMIZE_DEPENDENCIES feature from working effectively with Ninja has been fixed in CMake 3.28. The note in the Optimizing Build Dependencies section has been updated accordingly.

Test Resources And Constraints chapter:

  • CMake 3.28 added support for generating the test resource spec file at test time in a nominated test case. The Specifying Available System Resources sub-section explains how to use this new feature.

Test Frameworks chapter:

  • From Xcode 15, CMake cannot run gtest test discovery as a POST_BUILD step. The executable won’t yet be code-signed and fails to run. A note was added to highlight that the project must use PRE_TEST to avoid this limitation. The existing advice already recommended using PRE_TEST in all situations anyway.

Static Code Analysis chapter:

  • A new File Sets Header Verification section was added. Most of the material in this section was previously found in the File Sets subsection of the Installing chapter. The Recommended Practices section was also updated to move and expand some of the associated recommendations from that chapter to here.
  • The Disabling Checks For Some Files section was moved to later in the chapter after the new File Sets Header Verification section for better overall flow.

Dynamic Code Analysis chapter:

  • Fixed malformed command line in the Xcode Generator section where a line continuation was missing on the cmake --build example.

Finding Things chapter:

  • CMake 3.28 dropped the special Windows-only additional behavior of some find_...() commands relating to how the PATH environment variable is used.
  • The pkg_get_variable() command from the FindPkgConfig module gained a new DEFINE_VARIABLES keyword in CMake 3.28.

Installing chapter:

  • A new Installing C++20 Modules section was added to cover the installation part of the C++20 module support added in CMake 3.28. The new section discusses how to install a library that exports a C++20 module, along with some of the issues surrounding BMI files. It is closely related to the symbol visibility material added in the Libraries chapter, and extends that chapter’s example to demonstrate its installation.
  • The install(TARGETS) command gained a new CXX_MODULES entity type in CMake 3.28.
  • The install(EXPORT) command gained a new CXX_MODULES_DIRECTORY keyword in CMake 3.28.
  • The File Sets section has been refactored, with much of the material moving to earlier chapters. This section now focuses on just the installation aspects of file sets.
  • Advice was added to the Recommended Practices section regarding the use and installation of C++20 modules.
  • All uses of foo and bar have been replaced with alternative names throughout the chapter.

FetchContent chapter:

  • CMake 3.28 added a new EXCLUDE_FROM_ALL option to FetchContent_Declare().

Presets chapter:

  • CMake 3.28 added presets schema version 8, which is a minor change that only adds support for a new $schema field.

Working With Qt chapter:

  • Fixed a wrong cross-reference to the Packaging chapter, which previously linked to the Packaging section in the Getting Started Guide by mistake.