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