Ninja 多配置¶
在 3.17 版本中添加。
生成多个 build-<Config>.ninja
文件。
此生成器非常类似于 Ninja
生成器,但有一些关键区别。本文档将仅讨论这些区别。
与 Ninja
生成器不同,Ninja 多配置
使用 CMAKE_CONFIGURATION_TYPES
一次生成多个配置,而不是像 CMAKE_BUILD_TYPE
那样只生成一个配置。将为每个配置生成一个 build-<Config>.ninja
文件(其中 <Config>
是配置名称)。这些文件旨在与 ninja -f build-<Config>.ninja
一起运行。还会生成一个 build.ninja
文件,它使用来自 CMAKE_DEFAULT_BUILD_TYPE
或 CMAKE_CONFIGURATION_TYPES
中的第一个项目的配置。
cmake --build . --config <Config>
将始终使用 build-<Config>.ninja
进行构建。如果没有指定 --config
参数,则 cmake --build .
将使用 build.ninja
。
每个 build-<Config>.ninja
文件都包含 <target>
目标以及 <target>:<Config>
目标,其中 <Config>
与 build-<Config>.ninja
中指定的配置相同。此外,如果启用了跨配置模式,则 build-<Config>.ninja
可能包含 <target>:<OtherConfig>
目标,其中 <OtherConfig>
是一个跨配置,以及 <target>:all
,它在所有跨配置中构建目标。有关如何启用跨配置模式,请参见下文。
Ninja 多配置
生成器识别以下变量
CMAKE_CONFIGURATION_TYPES
指定要构建的配置的总集合。与其他多配置生成器不同,此变量的默认值为
Debug;Release;RelWithDebInfo
。CMAKE_CROSS_CONFIGS
指定可从所有
build-<Config>.ninja
文件中获得的以分号分隔的列表形式的配置。CMAKE_DEFAULT_BUILD_TYPE
指定
build.ninja
文件中默认使用的配置。CMAKE_DEFAULT_CONFIGS
指定在
build.ninja
中,如果没有指定:<Config>
后缀,则为目标构建的以分号分隔的列表形式的配置。
考虑以下示例
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)
现在假设您使用 Ninja 多配置
配置项目并运行以下命令之一
ninja -f build-Debug.ninja generated
# OR
cmake --build . --config Debug --target generated
这将构建 generator
的 Debug
配置,这将用于生成 generated.c
,而 generated.c
将用于构建 generated
的 Debug
配置。
但是,如果 CMAKE_CROSS_CONFIGS
设置为 all
,并且您改为运行以下命令
ninja -f build-Release.ninja generated:Debug
# OR
cmake --build . --config Release --target generated:Debug
这将构建 generator
的 Release
配置,这将用于生成 generated.c
,而 generated.c
将用于构建 generated
的 Debug
配置。这对于在仍然构建使用生成的代码构建的目标的调试版本时,运行生成器实用程序的发布优化版本非常有用。
自定义命令¶
在 3.20 版本中添加。
Ninja 多配置
生成器通过其跨配置模式为 add_custom_command()
和 add_custom_target()
添加了额外的功能。COMMAND
、DEPENDS
和 WORKING_DIRECTORY
参数可以在“命令配置”(正在使用的 build-<Config>.ninja
文件的“原生”配置)或“输出配置”(用于评估 OUTPUT
和 BYPRODUCTS
的配置)的上下文中进行评估。
如果 OUTPUT
或 BYPRODUCTS
命名了一个多个配置共有的路径(例如,它不使用任何生成器表达式),则默认情况下所有参数都在命令配置中评估。如果所有 OUTPUT
和 BYPRODUCTS
路径对于每个配置都是唯一的(例如,通过使用 $<CONFIG>
生成器表达式),则默认情况下,COMMAND
的第一个参数仍然在命令配置中评估,而所有后续参数以及 DEPENDS
和 WORKING_DIRECTORY
的参数都在输出配置中评估。这些默认值可以使用 $<OUTPUT_CONFIG:...>
和 $<COMMAND_CONFIG:...>
生成器表达式覆盖。请注意,如果目标通过其名称在 DEPENDS
中指定,或者作为 COMMAND
的第一个参数,则始终在命令配置中评估,即使它被包装在 $<OUTPUT_CONFIG:...>
中也是如此(因为它的纯名称不是生成器表达式)。
例如,考虑以下情况
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>>"
)
假设 generator
、tgt1
、tgt2
、tgt3
和 tgt4
都是可执行目标,并假设 $<CONFIG>.txt
是在使用 Release
命令配置的 Debug
输出配置中构建的。generator
目标的 Release
构建以 Debug.txt Debug Release
作为参数调用。该命令依赖于 tgt1
和 tgt4
的 Release
构建,以及 tgt2
和 tgt3
的 Debug
构建。
目标的 PRE_BUILD
、PRE_LINK
和 POST_BUILD
自定义命令仅在其“原生”配置(build-Release.ninja
文件中的 Release
配置)中运行,除非它们没有 BYPRODUCTS
或其 BYPRODUCTS
在每个配置中都是唯一的。考虑以下示例
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
)
在此示例中,如果您在 build-Release.ninja
中构建 exe:Debug
,则第一个和第二个自定义命令将运行,因为它们的副产品在每个配置中都是唯一的,但最后一个自定义命令不会运行。但是,如果您在 build-Release.ninja
中构建 exe:Release
,则所有三个自定义命令都将运行。