Ninja Multi-Config — CMake 3.27.7 Documentation

# Ninja Multi-Config

New 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

New 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.