Ninja Multi-Config¶
Added in version 3.17.
Generates multiple build-<Config>.ninja
files.
This generator is very much like the Ninja
generator, but with
some key differences. Only these differences will be discussed in this
document.
Unlike the Ninja
generator, Ninja Multi-Config
generates
multiple configurations at once with CMAKE_CONFIGURATION_TYPES
instead of only one configuration with CMAKE_BUILD_TYPE
. One
build-<Config>.ninja
file will be generated for each of these
configurations (with <Config>
being the configuration name.) These files
are intended to be run with ninja -f build-<Config>.ninja
. A
build.ninja
file is also generated, using the configuration from either
CMAKE_DEFAULT_BUILD_TYPE
or the first item from
CMAKE_CONFIGURATION_TYPES
.
cmake --build . --config <Config>
will always use build-<Config>.ninja
to build. If no --config
argument is
specified, cmake --build .
will use build.ninja
.
Each build-<Config>.ninja
file contains <target>
targets as well as
<target>:<Config>
targets, where <Config>
is the same as the
configuration specified in build-<Config>.ninja
Additionally, if
cross-config mode is enabled, build-<Config>.ninja
may contain
<target>:<OtherConfig>
targets, where <OtherConfig>
is a cross-config,
as well as <target>:all
, which builds the target in all cross-configs. See
below for how to enable cross-config mode.
The Ninja Multi-Config
generator recognizes the following variables:
CMAKE_CONFIGURATION_TYPES
Specifies the total set of configurations to build. Unlike with other multi-config generators, this variable has a value of
Debug;Release;RelWithDebInfo
by default.CMAKE_CROSS_CONFIGS
Specifies a semicolon-separated list of configurations available from all
build-<Config>.ninja
files.CMAKE_DEFAULT_BUILD_TYPE
Specifies the configuration to use by default in a
build.ninja
file.CMAKE_DEFAULT_CONFIGS
Specifies a semicolon-separated list of configurations to build for a target in
build.ninja
if no:<Config>
suffix is specified.
Consider the following example:
cmake_minimum_required(VERSION 3.16)
project(MultiConfigNinja C)
add_executable(generator generator.c)
add_custom_command(OUTPUT generated.c COMMAND generator generated.c)
add_library(generated ${CMAKE_BINARY_DIR}/generated.c)
Now assume you configure the project with Ninja Multi-Config
and run one of
the following commands:
ninja -f build-Debug.ninja generated
# OR
cmake --build . --config Debug --target generated
This would build the Debug
configuration of generator
, which would be
used to generate generated.c
, which would be used to build the Debug
configuration of generated
.
But if CMAKE_CROSS_CONFIGS
is set to all
, and you run the
following instead:
ninja -f build-Release.ninja generated:Debug
# OR
cmake --build . --config Release --target generated:Debug
This would build the Release
configuration of generator
, which would be
used to generate generated.c
, which would be used to build the Debug
configuration of generated
. This is useful for running a release-optimized
version of a generator utility while still building the debug version of the
targets built with the generated code.
Custom Commands¶
Added in version 3.20.
The Ninja Multi-Config
generator adds extra capabilities to
add_custom_command()
and add_custom_target()
through its
cross-config mode. The COMMAND
, DEPENDS
, and WORKING_DIRECTORY
arguments can be evaluated in the context of either the "command config" (the
"native" configuration of the build-<Config>.ninja
file in use) or the
"output config" (the configuration used to evaluate the OUTPUT
and
BYPRODUCTS
).
If either OUTPUT
or BYPRODUCTS
names a path that is common to
more 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 $<CONFIG>
generator expression), the first argument of
COMMAND
is still evaluated in the command config by default, while all
subsequent arguments, as well as the arguments to DEPENDS
and
WORKING_DIRECTORY
, are evaluated in the output config. These defaults can
be overridden with the $<OUTPUT_CONFIG:...>
and $<COMMAND_CONFIG:...>
generator-expressions. Note that if a target is specified by its name in
DEPENDS
, or as the first argument of COMMAND
, it is always evaluated
in the command config, even if it is wrapped in $<OUTPUT_CONFIG:...>
(because its plain name is not a generator expression).
As an example, consider the following:
add_custom_command(
OUTPUT "$<CONFIG>.txt"
COMMAND
generator "$<CONFIG>.txt"
"$<OUTPUT_CONFIG:$<CONFIG>>"
"$<COMMAND_CONFIG:$<CONFIG>>"
DEPENDS
tgt1
"$<TARGET_FILE:tgt2>"
"$<OUTPUT_CONFIG:$<TARGET_FILE:tgt3>>"
"$<COMMAND_CONFIG:$<TARGET_FILE:tgt4>>"
)
Assume that generator
, tgt1
, tgt2
, tgt3
, and tgt4
are all
executable targets, and assume that $<CONFIG>.txt
is built in the Debug
output config using the Release
command config. The Release
build of
the generator
target is called with Debug.txt Debug Release
as
arguments. The command depends on the Release
builds of tgt1
and
tgt4
, and the Debug
builds of tgt2
and tgt3
.
PRE_BUILD
, PRE_LINK
, and POST_BUILD
custom commands for targets
only get run in their "native" configuration (the Release
configuration in
the build-Release.ninja
file) unless they have no BYPRODUCTS
or their
BYPRODUCTS
are unique per config. Consider the following example:
add_executable(exe main.c)
add_custom_command(
TARGET exe
POST_BUILD
COMMAND
${CMAKE_COMMAND} -E echo "Running no-byproduct command"
)
add_custom_command(
TARGET exe
POST_BUILD
COMMAND
${CMAKE_COMMAND} -E echo
"Running separate-byproduct command for $<CONFIG>"
BYPRODUCTS $<CONFIG>.txt
)
add_custom_command(
TARGET exe
POST_BUILD
COMMAND
${CMAKE_COMMAND} -E echo
"Running common-byproduct command for $<CONFIG>"
BYPRODUCTS exe.txt
)
In this example, if you build exe:Debug
in build-Release.ninja
, the
first and second custom commands get run, since their byproducts are unique
per-config, but the last custom command does not. However, if you build
exe:Release
in build-Release.ninja
, all three custom commands get run.