Ninja Multi-config

2 views
Skip to first unread message

Jackie Bullinger

unread,
Aug 3, 2024, 10:42:59 AM8/3/24
to mistebumccimb

Unlike the Ninja generator, Ninja Multi-Config generatesmultiple configurations at once with CMAKE_CONFIGURATION_TYPESinstead of only one configuration with CMAKE_BUILD_TYPE. Onebuild-.ninja file will be generated for each of theseconfigurations (with being the configuration name.) These filesare intended to be run with ninja -f build-.ninja. Abuild.ninja file is also generated, using the configuration from eitherCMAKE_DEFAULT_BUILD_TYPE or the first item fromCMAKE_CONFIGURATION_TYPES.

Each build-.ninja file contains targets as well as: targets, where is the same as theconfiguration specified in build-.ninja Additionally, ifcross-config mode is enabled, build-.ninja may contain: targets, where is a cross-config,as well as :all, which builds the target in all cross-configs. Seebelow for how to enable cross-config mode.

This would build the Release configuration of generator, which would beused to generate generated.c, which would be used to build the Debugconfiguration of generated. This is useful for running a release-optimizedversion of a generator utility while still building the debug version of thetargets built with the generated code.

The Ninja Multi-Config generator adds extra capabilities toadd_custom_command() and add_custom_target() through itscross-config mode. The COMMAND, DEPENDS, and WORKING_DIRECTORYarguments can be evaluated in the context of either the "command config" (the"native" configuration of the build-.ninja file in use) or the"output config" (the configuration used to evaluate the OUTPUT andBYPRODUCTS).

If either OUTPUT or BYPRODUCTS names a path that is common tomore than one configuration (e.g. it does not use any generator expressions),all arguments are evaluated in the command config by default.If all OUTPUT and BYPRODUCTS paths are unique to each configuration(e.g. by using the $ generator expression), the first argument ofCOMMAND is still evaluated in the command config by default, while allsubsequent arguments, as well as the arguments to DEPENDS andWORKING_DIRECTORY, are evaluated in the output config. These defaults canbe overridden with the $ and $generator-expressions. Note that if a target is specified by its name inDEPENDS, or as the first argument of COMMAND, it is always evaluatedin the command config, even if it is wrapped in $(because its plain name is not a generator expression).

Assume that generator, tgt1, tgt2, tgt3, and tgt4 are allexecutable targets, and assume that $.txt is built in the Debugoutput config using the Release command config. The Release build ofthe generator target is called with Debug.txt Debug Release asarguments. The command depends on the Release builds of tgt1 andtgt4, and the Debug builds of tgt2 and tgt3.

PRE_BUILD, PRE_LINK, and POST_BUILD custom commands for targetsonly get run in their "native" configuration (the Release configuration inthe build-Release.ninja file) unless they have no BYPRODUCTS or theirBYPRODUCTS are unique per config. Consider the following example:

In this example, if you build exe:Debug in build-Release.ninja, thefirst and second custom commands get run, since their byproducts are uniqueper-config, but the last custom command does not. However, if you buildexe:Release in build-Release.ninja, all three custom commands get run.

cmake --build . --config will always use build-.ninjato build. If no --config argument is specified, cmake --build . willdefault to build-Debug.ninja, unless a build.ninja is generated (seebelow), in which case that will be used instead.

The Ninja Multi-Config generator generates .ninja files, just like the traditional single-config Ninja generator. However, it generates these files for multiple configurations, similar to the Visual Studio and XCode generators. This means that, for the first time ever, CMake supports multi-configuration builds on Linux and all other supported platforms. (Until the development of this feature, only Windows and MacOS could do multi-configuration builds using Visual Studio and XCode, respectively.)

When using the Ninja Multi-Config generator, multiple build-.ninja files are generated, one for each configuration in CMAKE_CONFIGURATION_TYPES. Select a configuration by running ninja -f build-.ninja , which will build in the selected configuration. And of course, you can also use cmake --build . --config to build instead.

One of the more advanced features of the Ninja Multi-Config generator is cross-config mode. In this mode, you can use tools built in one configuration to run custom commands for another configuration. For example, you can run the release version of a code generation tool to generate some code, which will then be compiled in the debug configuration. This is useful for building targets in debug mode without having to use the slower debug versions of the tools used to generate the code.

Proposed change: Get rid of CMAKE_NMC_DEFAULT_BUILD_FILE_CONFIG and use the first config listed in CMAKE_CONFIGURATION_TYPES instead. This also means there will always be a default configuration and there will always be a build.ninja file.

The separate pages that document each variable contain minimal content and instead refer back to the main Ninja Multi-Config page for details. This seems backwards. These separate pages are supposed to be the definitive reference for these variables, so they should be the most detailed and contain all information relevant to them.

Proposed change: Move the detailed descriptions into the individual variable pages and use the main Ninja Multi-Config generator page to focus on examples and how the variables work together. The main generator page could become more scenario-based rather than feature/variable-based.

I like the suggestion to drop the _NMC part of the variable names. That way the same settings can be used for other future multi-config generators. For now we document them as only available for this generator. We should add errors to the other generators if the variables are set on a generator that does not support them (to leave room for enabling them in the future).

Therefore I think we can go ahead and also rename CMAKE,_NMC_DEFAULT_BUILD_FILE_CONFIG to CMAKE_DEFAULT_BUILD_TYPE. Using it for cmake --build . makes sense too, though note for that we can only do it if it is literally in CMakeCache.txt.

I kind of did this deliberately. One of the things I find somewhat frustrating about the documentation is that there are lots of individual pages to learn about the many features (or components of a single feature), but not much in the way of a central outline to give a holistic view of how to use it.

At the risk of taking this too far, I wonder if we should also consider using CMAKE_DEFAULT_BUILD_TYPE to provide the initial value for CMAKE_BUILD_TYPE for single-config generators (if not set already)? This could be an opportunity to stop making an empty build type the default on single config generators and instead have it be Debug (which is what people typically assume it actually is). We could do this under the control of a policy to preserve backward compatibility.

We generally recommend usingNinja with CMake,especially for large projects.Ninja speeds up rebuild times significantly and avoids erratic problems with slower GNU Make.CMake also has theNinja Multi-Configgenerator

that allows building multiple build configuration types e.g. Debug, Release without CMake regenerating build*.ninja files for each build type with totally distinct build root directories.

Configuring medium-sized to large CMake projects in Qt Creator can be a challenge due to the number of variables that you need to pass to CMake to configure the project correctly. To make this easier, Qt Creator creates an initial configuration for you based on the kit preferences and displays it in Initial Configuration in the Build Settings of the project. Or, you can use CMake presets to configure CMake.

You can specify additional CMake options, such as --find-debug, --trace-expand, or --warn-uninitialized, in Additional CMake options. For more information about the options, click the link in the field name or see CMake: cmake(1).

Initial Configuration lists the variables that Qt Creator uses to configure the CMake project for the first time. It shows the default values that come from the kit's CMake configuration in italics. Qt Creator saves the initial configuration list of variables in the project's source directory as the CMakeLists.txt.user file.

Current Configuration lists the CMake variables in the cmake-file-api JSON export in the .cmake/api/v1/reply directory. It shows the variables that come from the initial configuration in italics and mismatched values in red.

After selecting the Run CMake button, you can view and change the actual values of the variables that Qt Creator passes to CMake. The Key column lists variable names, and the Value column lists their current values. For more information about the variables, select Help in the context menu or see CMake: cmake-variables(7). For more information about Qt-specific variables, see CMake Variable Reference.

c80f0f1006
Reply all
Reply to author
Forward
0 new messages