Skip to content

Ninja: Add multi-config variant NinjaMulti

This is a WIP! This PR is submitted for general feedback from those more knowledgeable than I on what I may have gotten wrong, problems I may not have foreseen, and ways this could be improved.

Alternatively, this MR could be rejected out-right, saving me from spending additional time to finish polishing something that will ultimately prove fruitless.


Hold on to your hats: This one's a doozy.

This change introduces a NinjaMulti generator (to be used with -GNinjaMulti). It behaves like a multiconf generator (like MSBuild/VS generators), and supports building multiple build types in parallel from a single build tree. Without an IDE, CMake hasn't so far been able to do multiple build types in parallel, nor within a single build tree.

This change required quite a bit of prodding at the Makefile and Ninja generator code to make sure a it worked with multiple build types, rather than assuming a single CMake invocation will only generate one build type.

The modifications aren't complex, and almost all of the original Ninja generator code is used. The NinjaMulti generator is a subclass of the main Ninja generator, but the NinjaMulti generator implements virtual bool IsMultiConf() method, and the code that once generated for a single build type now generates for multiple build types in a loop (using the non-virtual std::vector<std::string> GetBuildConfigurations() method).

In the case of IsMultiConf() == false (the original Ninja generator), GetBuildConfigurations() will simply return CMAKE_BUILD_TYPE, effectively causing the loops to generate the single active build type. If IsMultiConf() == true, GetBuildConfigurations() will instead return CMAKE_CONFIGURATION_TYPES.

Many generate file paths (such as object files) will be qualified by the build type for which it is generating. The primary output files will only be qualified with a build type if IsMultiConf() == true.

The all target in a multi-conf Ninja file depends on one or more all:<config> targets, each of which depend on the outputs of the targets for the respective <config>. all is still the default target in the generated build.ninja. The list of all:<config> sub-targets is configured using CMAKE_DEFAULT_BUILD_TYPES, which defaults to Debug;Release. This has the effect that running ninja [all] will only build Debug and Release, while additional configurations may still be explicitly requested via ninja all:<config>. It is most common that users want to use Debug and Release (rather than MinSizeRel or RelWithDebInfo), so Debug;Release was chosen as the default build types.

Note that this is still a WIP! This doesn't yet have the required support for cmake --build . --config <config> nor ctest -C <config>, and you cannot yet ninja my-target:Debug to build Debug of target. Building ninja my-target will build all of CMAKE_CONFIGURATION_TYPES, where it should also respect CMAKE_DEFAULT_BUILD_TYPES.

Topic-rename: ninja-multiconf

Edited by Brad King

Merge request reports