Qt Creator 9 - CMakePresets

CMake introduced with version 3.19 the concept of cmake-presets.

The introduction in the CMake documentation reads as:

One problem that CMake users often face is sharing settings with other people for common ways to configure a project. This may be done to support CI builds, or for users who frequently use the same build. CMake supports two files, CMakePresets.json and CMakeUserPresets.json, that allow users to specify common configure options and share them with others.

The CMake presets come with a Version field, which gets incremented after every new feature added.

Qt Creator supports presets up to version 3 (introduced in CMake 3.21), but the version checking is not enforced. All the fields from version 3 are read and used if present.

The CMake presets support has been implemented ontop of Qt Creator’s Build import feature.

This means that Qt Creator 9 offers the presets configuration only on the very first CMake project configuration (when no CMakeLists.txt.user file exists, or all the Kits have been disabled in the project).

Configure presets

They are part of the CMake presets version 1. Below is one example that configures a Qt project with the:

  • LLVM-MinGW compiler
  • build directory – <sourceDir>/build-release
  • build type – CMAKE_BUILD_TYPE as Release
  • generator – MinGW Makefiles
  • explicit CMake executable
  • path to Qt installation via CMAKE_PREFIX_PATH
{
  "version": 1,
  "configurePresets": [
    {
      "name": "llvm-mingw",
      "displayName": "LLVM-MinGW 15.0.0",
      "generator": "MinGW Makefiles",
      "binaryDir": "${sourceDir}/build-release",
      "cmakeExecutable": "C:/Tools/cmake-3.24.2-windows-arm64/bin/cmake.exe",
      "cacheVariables": {
        "CMAKE_BUILD_TYPE": "Release",
        "CMAKE_PREFIX_PATH": "C:/Qt/6.4.0/llvm-mingw_arm64"
      },
      "environment": {
        "PATH": "C:/llvm-mingw/bin;$penv{PATH}"
      }
    }
  ]
}

I’ve tested a Qt Widgets example with Qt Creator 9 with a clean configuration:

  • No CMake tool
  • No Kit
  • No Compilers
  • No Qt

cmake-presets-llvm-mingw

As you could see above, Qt Creator has created a Kit named LLVM-MinGW 15.0.0 (CMake preset), configured the compilers, registered the Qt version, the CMake tool, and lastly the cacheVariables were added to the Initial Configuration project settings page.

Then the project was able to be built and run successfully.

Note that on this Windows 11 Arm64 laptop I have built Qt, Qt Creator natively for Arm64 myself, to simulate the case where Qt SDK cannot be used.

Compiler detection

In the configure preset above there was no compiler specified via the CMAKE_C_COMPILER and CMAKE_CXX_COMPILER variables in the cacheVariables section.

In this case Qt Creator creates a CMake compiler probe project, configures it with the environment specified by the preset, and then extracts the compiler information.

Note that on Windows this operation is not insignificant, and adds up with the number of presets defined.

Build presets

They are part of the CMake presets version 2. They allow configuration of the build steps.

Below you have an example that configures the same Qt project:

  • generator Ninja Multi-Config
  • defines two build steps Debug and Release
  • specifies the path to ninja.exe as part of the CMAKE_MAKE_PROGRAM variable
{
  "version": 2,
  "configurePresets": [
    {
      "name": "ninja-nmc",
      "displayName": "Ninja Multi-Config LLVM-MinGW",
      "generator": "Ninja Multi-Config",
      "binaryDir": "${sourceDir}/build",
      "cacheVariables": {
        "CMAKE_CONFIGURATION_TYPES": "Debug;Release",
        "CMAKE_PREFIX_PATH": "C:/Qt/6.4.0/llvm-mingw_arm64",
        "CMAKE_MAKE_PROGRAM": "C:/Tools/ninja-1.10.2/ninja.exe"
      },
      "environment": {
        "PATH": "C:/llvm-mingw/bin;$penv{PATH}"
      }
    }
  ],
  "buildPresets": [
    {
      "name": "release",
      "displayName": "Ninja Release",
      "configurePreset": "ninja-nmc",
      "configuration": "Release"
    },
    {
      "name": "debug",
      "displayName": "Ninja Debug",
      "configurePreset": "ninja-nmc",
      "configuration": "Debug"
    }
  ]
}

cmake-presets-multi-ninja

As you could see above, Qt Creator 9 configured the project with the two build steps, and when I enabled the second build step, I could build the two configurations Debug and Release in one go.

Visual C++ and the Ninja generator

CMake can use the Visual C++ compiler super easy with the Visual Studio 17 2022 generator:

      "generator": "Visual Studio 17 2022",
      "architecture": "ARM64"

But this will generate a MSBuild project.

The Visual C++ compiler in order to be used successfuly requires the proper environment to be present when invoked.

This is usually done via the vcvarsall.bat batch file.

Since Qt Creator runs the CMake compiler probe with the system environment the Visual C++ compiler environment needs to be explicitly specified.

Below you have such an example preset:

{
  "version": 3,
  "configurePresets": [
    {
      "name": "visualc-ninja",
      "displayName": "Visual C++ 2022 arm64 Ninja",
      "generator": "Ninja",
      "binaryDir": "${sourceDir}/build-${presetName}",
      "cacheVariables": {
        "CMAKE_BUILD_TYPE": "Release",
        "CMAKE_PREFIX_PATH": "C:/Qt/6.4.0/msvc2019_arm64"
      },
      "environment" : {
        "VCToolsVersion": "14.34.31931",
        "WindowsSDKVersion" : "10.0.22621.0",
        "VCArch": "arm64",
        "VCHostArch": "HostARM64",
        "VCToolsInstallDir": "$env{ProgramFiles}/Microsoft Visual Studio/2022/Preview/VC/Tools/MSVC/$env{VCToolsVersion}",
        "WindowsSdkDir" : "$env{ProgramFiles(x86)}/Windows Kits/10",
        "WindowsSdkIncVerDir": "$env{WindowsSdkDir}/Include/$env{WindowsSDKVersion}",
        "WindowsSdkLibVerDir": "$env{WindowsSdkDir}/Lib/$env{WindowsSDKVersion}",

        "INCLUDE": "$env{VCToolsInstallDir}/ATLMFC/include;$env{VCToolsInstallDir}/include;$env{WindowsSdkIncVerDir}/ucrt;$env{WindowsSdkIncVerDir}/shared;$env{WindowsSdkIncVerDir}/um;$env{WindowsSdkIncVerDir}/winrt;$env{WindowsSdkIncVerDir}/cppwinrt",
        "LIB": "$env{VCToolsInstallDir}/ATLMFC/lib/$env{VCArch};$env{VCToolsInstallDir}/lib/$env{VCArch};$env{WindowsSdkLibVerDir}/ucrt/$env{VCArch};$env{WindowsSdkLibVerDir}/um/$env{VCArch}",
        "PATH": "C:/Tools/ninja-1.10.2/;$env{VCToolsInstallDir}/bin/$env{VCHostArch}/$env{VCArch};$env{WindowsSdkDir}/bin/$env{WindowsSDKVersion}/$env{VCArch};$penv{PATH}"
      }
    }
  ],
  "buildPresets": [
    {
      "name": "visualc-ninja",
      "configurePreset": "visualc-ninja"
    }
  ]
}

And here you can see it in action:

cmake-presets-visualc-ninja

The above environment variables can be also set in Qt Creator’s Environment -> System settings, and would act as the default compiler on Windows, in the same way as gcc and clang are present on other operating systems.

The above step is equivalent with calling Qt Creator from a vcvarsall.bat configured shell.

I gathered the version numbers from such a vcvarsall.bat configured shell by running:

$ set | findstr Ver
$ where cl

Conditions

Come with CMake presets version 3. Test presets are also part of this version but Qt Creator 9 does not support them.

Below you have an example preset that comes with a Linux and a Windows preset.

{
  "version": 3,
  "configurePresets": [
    {
      "name": "linux",
      "displayName": "Linux GCC",
      "binaryDir": "${sourceDir}/build",
      "cacheVariables": {
        "CMAKE_PREFIX_PATH": "$env{HOME}/Qt/6.4.0/gcc_aarch64"
      },
      "condition": {
        "type": "equals",
        "lhs": "${hostSystemName}",
        "rhs": "Linux"
      }
    },
    {
      "name": "windows",
      "displayName": "Windows MSVC",
      "binaryDir": "${sourceDir}/build",
      "cacheVariables": {
        "CMAKE_PREFIX_PATH": "$env{SYSTEMDRIVE}/Qt/6.4.0/msvc2019_arm64"
      },
      "condition": {
        "type": "equals",
        "lhs": "${hostSystemName}",
        "rhs": "Windows"
      }
    }
  ]
}

On Windows only the Windows preset will be displayed:

cmake-presets-cross-platform-windows

An on Linux (running with WSLg on WLS2 - Windows Subsystem for Linux) only the Linux preset will be displayed:

cmake-presets-cross-platform-linux

Note that I didn’t specify a generator field and Qt Creator picked the generator that CMake has selected as default for the platform.

Debugging

Presets reloading can oly be done in Qt Creator 9 manually, by deleting the build directory and the CMakeLists.txt.user file.

With Qt Creator 9 you can now remove folders in File system view (Alt+Y, Alt+F), which should help with this task.

The CMake compiler probe invocation, and the location of the CMakeCache.txt file can be logged via the environment variable QT_LOGGING_RULES=qtc.cmake.import*=true before starting Qt Creator.

Conclusion

Qt Creator 9 is the first version if Qt Creator that supports CMake presets, and the implementation can and may contain bugs.

I haven’t mentioned any Vendor specific settings, that’s because Qt Creator 9 doesn’t use any.

Which setting configuration would you want to be able to specify in a CMakePresets.json file?


Blog Topics:

Comments