Ninja Multi-Config | |
------------------ | |
.. versionadded:: 3.17 | |
Generates multiple ``build-<Config>.ninja`` files. | |
This generator is very much like the :generator:`Ninja` generator, but with | |
some key differences. Only these differences will be discussed in this | |
document. | |
Unlike the :generator:`Ninja` generator, ``Ninja Multi-Config`` generates | |
multiple configurations at once with :variable:`CMAKE_CONFIGURATION_TYPES` | |
instead of only one configuration with :variable:`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 | |
:variable:`CMAKE_DEFAULT_BUILD_TYPE` or the first item from | |
:variable:`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: | |
:variable:`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. | |
:variable:`CMAKE_CROSS_CONFIGS` | |
Specifies a :ref:`semicolon-separated list <CMake Language Lists>` of | |
configurations available from all ``build-<Config>.ninja`` files. | |
:variable:`CMAKE_DEFAULT_BUILD_TYPE` | |
Specifies the configuration to use by default in a ``build.ninja`` file. | |
:variable:`CMAKE_DEFAULT_CONFIGS` | |
Specifies a :ref:`semicolon-separated list <CMake Language Lists>` of | |
configurations to build for a target in ``build.ninja`` | |
if no ``:<Config>`` suffix is specified. | |
Consider the following example: | |
.. code-block:: cmake | |
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: | |
.. code-block:: shell | |
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 :variable:`CMAKE_CROSS_CONFIGS` is set to ``all``, and you run the | |
following instead: | |
.. code-block:: shell | |
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 | |
^^^^^^^^^^^^^^^ | |
.. versionadded:: 3.20 | |
The ``Ninja Multi-Config`` generator adds extra capabilities to | |
:command:`add_custom_command` and :command:`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: | |
.. code-block:: cmake | |
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: | |
.. code-block:: cmake | |
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. |