New features in CMake 3.18

On 15th of July Kitware has released CMake version 3.18. The release notes contain the list of changes.

Below you have some changes that should improve the life of a Qt developer using CMake.

Profiling support

Finding out where CMake is spending time configuring your project used to be difficult. Now with profiling support it got way easier.

The following command line parameters (which can be passed in Qt Creator 4.13 in the Initial CMake parameters project setting)

--profiling-format=google-trace
--profiling-output=qtcreator-cmake.json

will produce the a qtcreator-cmake.json file (40 MiB in size for Qt Creator) which can be loaded in Qt Creator via the Chrome Trace Format Viewer.

It looks like this:

qtcreator-cmake-profiling

This feature was tracked on Kitware's side at !2760.

Precompiled headers

CMake got precompiled header support in version 3.16, but since then new features were added to CMake, which didn’t support precompiled headers.

CMake 3.18 fixes the following use cases:

  • iOS multi-architecture (#20497)
  • Ninja Multi-Config with MSVC (#20711)
  • Ninja Multi-Config and reusable PCH for MSVC (#20721)

CMake 3.18 will run the AUTOMOC step after the generated sources step (PCH, Unity) has been run. This used to be the other way around.

This fixes #20119 which required Qt Creator to have CMake configure the project twice as a workaround.

The downside is that if you have header-only libraries with the Q_OBJECT macro and AUTOMOC set to ON, they will fail to compile with CMake 3.18. See #20980 and #20968 for more details.

To fix this you need to add a dummy source file to those libraries:

file(GENERATE
     OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/empty_pch.cxx
     CONTENT "/*empty file*/")
target_sources(CommonPCH_Lib PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/empty_pch.cxx)

Unity builds

The UNITY_BUILD_MODE target property was added to tell generators which algorithm to use for grouping included source files.

The default CMake 3.16 mode is BATCH, the newly added CMake 3.18 mode is GROUP.

add_library(example_library
            source1.cxx
            source2.cxx
            source3.cxx
            source4.cxx)

set_target_properties(example_library PROPERTIES
                      UNITY_BUILD_MODE BATCH
                      UNITY_BUILD_BATCH_SIZE 2)

Let’s say we have a naming conflict between source3.cxx and source4.cxx, since they are in the same batch, we would need to get creative in order to fix the problem.

Rather than having an object library with just source4.cxx, or change the order of the source files (source4.cxx, source1.cxx, source2.cxx, source3.cxx), we can now have the following:

add_library(example_library
            source1.cxx
            source2.cxx
            source3.cxx
            source4.cxx)

set_target_properties(example_library PROPERTIES
                      UNITY_BUILD_MODE GROUP)

set_source_files_properties(source1.cxx source2.cxx source3.cxx
                            PROPERTIES UNITY_GROUP "bucket1")
set_source_files_properties(source4.cxx
                            PROPERTIES UNITY_GROUP "bucket2")

This feature was tracked at Kitware's side at !4716.

Less compiler checks

Given the following C++ “Hello World” CMakeLists.txt:

cmake_minimum_required(VERSION 3.17)

project(hello)

add_executable(hello hello.cpp)

When configuring with CMake 3.17 we would get the following output:

$ cmake -E time cmake -G Ninja -S . -B build
-- The C compiler identification is MSVC 19.25.28614.0
-- The CXX compiler identification is MSVC 19.25.28614.0
-- Check for working C compiler: C:/Program Files (x86)/Microsoft Visual Studio/2019/BuildTools/VC/Tools/MSVC/14.25.28610/bin/Hostx64/x64/cl.exe
-- Check for working C compiler: C:/Program Files (x86)/Microsoft Visual Studio/2019/BuildTools/VC/Tools/MSVC/14.25.28610/bin/Hostx64/x64/cl.exe - works
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Detecting C compile features
-- Detecting C compile features - done
-- Check for working CXX compiler: C:/Program Files (x86)/Microsoft Visual Studio/2019/BuildTools/VC/Tools/MSVC/14.25.28610/bin/Hostx64/x64/cl.exe
-- Check for working CXX compiler: C:/Program Files (x86)/Microsoft Visual Studio/2019/BuildTools/VC/Tools/MSVC/14.25.28610/bin/Hostx64/x64/cl.exe - works
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Configuring done
-- Generating done
-- Build files have been written to: C:/Projects/c++/HelloWorld/build
Elapsed time: 4 s. (time), 3.825 s. (clock)

With CMake 3.18 we would get:

$ cmake -E time cmake -G Ninja -S . -B build
-- The C compiler identification is MSVC 19.25.28614.0
-- The CXX compiler identification is MSVC 19.25.28614.0
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Check for working C compiler: C:/Program Files (x86)/Microsoft Visual Studio/2019/BuildTools/VC/Tools/MSVC/14.25.28610/bin/Hostx64/x64/cl.exe - skipped
-- Detecting C compile features
-- Detecting C compile features - done
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Check for working CXX compiler: C:/Program Files (x86)/Microsoft Visual Studio/2019/BuildTools/VC/Tools/MSVC/14.25.28610/bin/Hostx64/x64/cl.exe - skipped
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Configuring done
-- Generating done
-- Build files have been written to: C:/Projects/c++/HelloWorld/build
Elapsed time: 2 s. (time), 2.029 s. (clock)

This is due to !4789 enable_language: Assume compiler works if ABI detection compiles!

CMake is now doing only two try_compile instead of four, one for each default language C and CXX.

By having:

cmake_minimum_required(VERSION 3.17)

project(hello LANGUAGES CXX)

add_executable(hello hello.cpp)

We can have only one try_compile:

$ cmake -E time cmake -G Ninja -S . -B build
-- The CXX compiler identification is MSVC 19.25.28614.0
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Check for working CXX compiler: C:/Program Files (x86)/Microsoft Visual Studio/2019/BuildTools/VC/Tools/MSVC/14.25.28610/bin/Hostx64/x64/cl.exe - skipped
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Configuring done
-- Generating done
-- Build files have been written to: C:/Projects/c++/HelloWorld/build
Elapsed time: 1 s. (time), 1.222 s. (clock)

This should help when compiling examples Qt6 with CMake from Qt Creator.

Qt6 speed up features

The following features will allow for leaner and faster Qt6 CMake code:

  • The file(CONFIGURE) subcommand was created in order to replicate the configure_file() functionality without resorting to a pre-existing file on disk as input. The content is instead passed as a string. #20388
  • The cmake_language() command was added for meta-operations on scripted or built-in commands, starting with a mode to CALL other commands, and EVAL CODE to inplace evaluate a CMake script. #18392, !4408
  • The set_property() command with the SOURCE scope gained the DIRECTORY and TARGET_DIRECTORY options to set properties in the provided directory scopes. #20128
  • The file() command gained the ARCHIVE_CREATE and ARCHIVE_EXTRACT subcommands to expose the cmake(1) -E tar functionality to CMake scripting code. #20443

Blog Topics:

Comments