New features in CMake 3.19

On 18th of November Kitware, has released CMake version 3.19. The release notes contain the list of changes.

Below you have some changes that caught my attention:

Presets

Configuring a Qt CMake project from command line requires the presence of a few mandatory arguments. For example:

cmake -GNinja -DCMAKE_BUILD_TYPE=Release -DCMAKE_PREFIX_PATH=c:/Qt/6.0.0/mingw81_64 -S . -B build

And usually some more -D arguments with specific options like -DQT_BUILD_EXAMPLES=ON or -DFEATURE_system_zlib=OFF and the command line becomes very long.

Scripts end up being used, which differ from developer to developer, and they might or not be cross-platform.

CMake 3.19 comes with support for CMakePresets.json and CMakeUserPresets.json files which help in this regard.

Here is an preset example that will build using the MinGW 8.1 compiler:

{
  "version": 1,
  "cmakeMinimumRequired": {
    "major": 3,
    "minor": 19,
    "patch": 0
  },
  "configurePresets": [
    {
      "name": "mingw",
      "displayName": "Ninja with MinGW 8.1",
      "generator": "Ninja",
      "binaryDir": "${sourceDir}/build",
      "cacheVariables": {
        "CMAKE_BUILD_TYPE": "Release",
        "CMAKE_PREFIX_PATH": "c:/Qt/6.0.0/mingw81_64"
      },
      "environment": {
        "PATH": "c:/Qt/Tools/Ninja;c:/Qt/Tools/mingw810_64/bin;$penv{PATH}"
      }
    }
  ]
}

Then, building a project resorts to just: cmake -S . --preset=mingw

This has been tracked as issue #21164, and documented at cmake-presets(7)

Xcode 12.0 and Apple Silicon

The Xcode generator now uses the Xcode “new build system” when generating for Xcode 12.0 or higher. See CMAKE_XCODE_BUILD_SYSTEM variable for Xcode build system selection.

Issue tracked at #18088

Apple Silicon is now supported (since CMake 3.19.2). See CMAKE_APPLE_SILICON_PROCESSOR for selecting an architecture different than CMAKE_HOST_SYSTEM_PROCESSOR detected by CMake.

Issue tracked at #21554

Precompile headers

For those using Clang 11 and onwards, the PCH_INSTANTIATE_TEMPLATES target property was added to enable template instantiation in the precompiled header.

This is enabled by default and may significantly improve compilation times.

For example, building Qt6Base with no examples / tests on my Lenovo A485 Ryzen 7 laptop running Windows 10 with Clang-MinGW 11, CMake 3.19.2. The values below are the median from four times.

-DCMAKE_PCH_INSTANTIATE_TEMPLATES=OFF

* build time: 919.5 s
* pch size: 397 MB

-DCMAKE_PCH_INSTANTIATE_TEMPLATES=ON (default)

* build time: 792.75 s
* pch size: 455 MB

That is a 13.78% speed increase, while having a 14.61% pch size increase.

Issue tracked at #21133

JSON parsing

The string() command gained a set of new JSON sub commands that provide JSON parsing capabilities.

For example, parsing the CMakePresets.json above to get the CMAKE_PREFIX_PATH variable:

file(READ CMakePresets.json cmakePresetsJson)
string(JSON prefixPath GET "${cmakePresetsJson}" configurePresets 0 cacheVariables CMAKE_PREFIX_PATH)
message("prefixPath: ${prefixPath}")

Issue tracked at #19501

“Destructor” support

The cmake_language() command gained a DEFER mode to schedule command calls to occur at the end of processing a directory.

This way, we can call a function at the end of configuration of a CMakeList.txt file, for example printing a summary of find_package calls:

function(at_exit)
  include(FeatureSummary)
  feature_summary(INCLUDE_QUIET_PACKAGES WHAT
    PACKAGES_FOUND PACKAGES_NOT_FOUND
    ENABLED_FEATURES DISABLED_FEATURES
  )
endfunction()
cmake_language(DEFER CALL at_exit)

This feature has been tracked at issue #19575 and allowed implementing some of Qt6’s functionality.


Blog Topics:

Comments