Ninja Multi-Config.rst 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177
  1. Ninja Multi-Config
  2. ------------------
  3. .. versionadded:: 3.17
  4. Generates multiple ``build-<Config>.ninja`` files.
  5. This generator is very much like the :generator:`Ninja` generator, but with
  6. some key differences. Only these differences will be discussed in this
  7. document.
  8. Unlike the :generator:`Ninja` generator, ``Ninja Multi-Config`` generates
  9. multiple configurations at once with :variable:`CMAKE_CONFIGURATION_TYPES`
  10. instead of only one configuration with :variable:`CMAKE_BUILD_TYPE`. One
  11. ``build-<Config>.ninja`` file will be generated for each of these
  12. configurations (with ``<Config>`` being the configuration name.) These files
  13. are intended to be run with ``ninja -f build-<Config>.ninja``. A
  14. ``build.ninja`` file is also generated, using the configuration from either
  15. :variable:`CMAKE_DEFAULT_BUILD_TYPE` or the first item from
  16. :variable:`CMAKE_CONFIGURATION_TYPES`.
  17. ``cmake --build . --config <Config>`` will always use ``build-<Config>.ninja``
  18. to build. If no :option:`--config <cmake--build --config>` argument is
  19. specified, :option:`cmake --build . <cmake --build>` will use ``build.ninja``.
  20. Each ``build-<Config>.ninja`` file contains ``<target>`` targets as well as
  21. ``<target>:<Config>`` targets, where ``<Config>`` is the same as the
  22. configuration specified in ``build-<Config>.ninja`` Additionally, if
  23. cross-config mode is enabled, ``build-<Config>.ninja`` may contain
  24. ``<target>:<OtherConfig>`` targets, where ``<OtherConfig>`` is a cross-config,
  25. as well as ``<target>:all``, which builds the target in all cross-configs. See
  26. below for how to enable cross-config mode.
  27. The ``Ninja Multi-Config`` generator recognizes the following variables:
  28. :variable:`CMAKE_CONFIGURATION_TYPES`
  29. Specifies the total set of configurations to build. Unlike with other
  30. multi-config generators, this variable has a value of
  31. ``Debug;Release;RelWithDebInfo`` by default.
  32. :variable:`CMAKE_CROSS_CONFIGS`
  33. Specifies a :ref:`semicolon-separated list <CMake Language Lists>` of
  34. configurations available from all ``build-<Config>.ninja`` files.
  35. :variable:`CMAKE_DEFAULT_BUILD_TYPE`
  36. Specifies the configuration to use by default in a ``build.ninja`` file.
  37. :variable:`CMAKE_DEFAULT_CONFIGS`
  38. Specifies a :ref:`semicolon-separated list <CMake Language Lists>` of
  39. configurations to build for a target in ``build.ninja``
  40. if no ``:<Config>`` suffix is specified.
  41. Consider the following example:
  42. .. code-block:: cmake
  43. cmake_minimum_required(VERSION 3.16)
  44. project(MultiConfigNinja C)
  45. add_executable(generator generator.c)
  46. add_custom_command(OUTPUT generated.c COMMAND generator generated.c)
  47. add_library(generated ${CMAKE_BINARY_DIR}/generated.c)
  48. Now assume you configure the project with ``Ninja Multi-Config`` and run one of
  49. the following commands:
  50. .. code-block:: shell
  51. ninja -f build-Debug.ninja generated
  52. # OR
  53. cmake --build . --config Debug --target generated
  54. This would build the ``Debug`` configuration of ``generator``, which would be
  55. used to generate ``generated.c``, which would be used to build the ``Debug``
  56. configuration of ``generated``.
  57. But if :variable:`CMAKE_CROSS_CONFIGS` is set to ``all``, and you run the
  58. following instead:
  59. .. code-block:: shell
  60. ninja -f build-Release.ninja generated:Debug
  61. # OR
  62. cmake --build . --config Release --target generated:Debug
  63. This would build the ``Release`` configuration of ``generator``, which would be
  64. used to generate ``generated.c``, which would be used to build the ``Debug``
  65. configuration of ``generated``. This is useful for running a release-optimized
  66. version of a generator utility while still building the debug version of the
  67. targets built with the generated code.
  68. Custom Commands
  69. ^^^^^^^^^^^^^^^
  70. .. versionadded:: 3.20
  71. The ``Ninja Multi-Config`` generator adds extra capabilities to
  72. :command:`add_custom_command` and :command:`add_custom_target` through its
  73. cross-config mode. The ``COMMAND``, ``DEPENDS``, and ``WORKING_DIRECTORY``
  74. arguments can be evaluated in the context of either the "command config" (the
  75. "native" configuration of the ``build-<Config>.ninja`` file in use) or the
  76. "output config" (the configuration used to evaluate the ``OUTPUT`` and
  77. ``BYPRODUCTS``).
  78. If either ``OUTPUT`` or ``BYPRODUCTS`` names a path that is common to
  79. more than one configuration (e.g. it does not use any generator expressions),
  80. all arguments are evaluated in the command config by default.
  81. If all ``OUTPUT`` and ``BYPRODUCTS`` paths are unique to each configuration
  82. (e.g. by using the :genex:`$<CONFIG>` generator expression), the first argument of
  83. ``COMMAND`` is still evaluated in the command config by default, while all
  84. subsequent arguments, as well as the arguments to ``DEPENDS`` and
  85. ``WORKING_DIRECTORY``, are evaluated in the output config. These defaults can
  86. be overridden with the :genex:`$<OUTPUT_CONFIG:...>` and :genex:`$<COMMAND_CONFIG:...>`
  87. generator-expressions. Note that if a target is specified by its name in
  88. ``DEPENDS``, or as the first argument of ``COMMAND``, it is always evaluated
  89. in the command config, even if it is wrapped in :genex:`$<OUTPUT_CONFIG:...>`
  90. (because its plain name is not a generator expression).
  91. As an example, consider the following:
  92. .. code-block:: cmake
  93. add_custom_command(
  94. OUTPUT "$<CONFIG>.txt"
  95. COMMAND
  96. generator "$<CONFIG>.txt"
  97. "$<OUTPUT_CONFIG:$<CONFIG>>"
  98. "$<COMMAND_CONFIG:$<CONFIG>>"
  99. DEPENDS
  100. tgt1
  101. "$<TARGET_FILE:tgt2>"
  102. "$<OUTPUT_CONFIG:$<TARGET_FILE:tgt3>>"
  103. "$<COMMAND_CONFIG:$<TARGET_FILE:tgt4>>"
  104. )
  105. Assume that ``generator``, ``tgt1``, ``tgt2``, ``tgt3``, and ``tgt4`` are all
  106. executable targets, and assume that ``$<CONFIG>.txt`` is built in the ``Debug``
  107. output config using the ``Release`` command config. The ``Release`` build of
  108. the ``generator`` target is called with ``Debug.txt Debug Release`` as
  109. arguments. The command depends on the ``Release`` builds of ``tgt1`` and
  110. ``tgt4``, and the ``Debug`` builds of ``tgt2`` and ``tgt3``.
  111. ``PRE_BUILD``, ``PRE_LINK``, and ``POST_BUILD`` custom commands for targets
  112. only get run in their "native" configuration (the ``Release`` configuration in
  113. the ``build-Release.ninja`` file) unless they have no ``BYPRODUCTS`` or their
  114. ``BYPRODUCTS`` are unique per config. Consider the following example:
  115. .. code-block:: cmake
  116. add_executable(exe main.c)
  117. add_custom_command(
  118. TARGET exe
  119. POST_BUILD
  120. COMMAND
  121. ${CMAKE_COMMAND} -E echo "Running no-byproduct command"
  122. )
  123. add_custom_command(
  124. TARGET exe
  125. POST_BUILD
  126. COMMAND
  127. ${CMAKE_COMMAND} -E echo
  128. "Running separate-byproduct command for $<CONFIG>"
  129. BYPRODUCTS $<CONFIG>.txt
  130. )
  131. add_custom_command(
  132. TARGET exe
  133. POST_BUILD
  134. COMMAND
  135. ${CMAKE_COMMAND} -E echo
  136. "Running common-byproduct command for $<CONFIG>"
  137. BYPRODUCTS exe.txt
  138. )
  139. In this example, if you build ``exe:Debug`` in ``build-Release.ninja``, the
  140. first and second custom commands get run, since their byproducts are unique
  141. per-config, but the last custom command does not. However, if you build
  142. ``exe:Release`` in ``build-Release.ninja``, all three custom commands get run.