Ninja 多配置¶
在 3.17 版本中添加。
生成多个 build-<Config>.ninja 文件。
此生成器与 Ninja 生成器非常相似,但有一些关键区别。本文档仅讨论这些区别。
与 Ninja 生成器不同,Ninja Multi-Config 通过 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 中指定的配置相同。此外,如果启用了跨配置(cross-config)模式,build-<Config>.ninja 可能包含 <target>:<OtherConfig> 目标(其中 <OtherConfig> 是跨配置),以及 <target>:all(用于在所有跨配置中构建该目标)。请参阅下文了解如何启用跨配置模式。
Ninja Multi-Config 生成器识别以下变量:
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 Multi-Config 配置了项目并运行了以下命令之一:
ninja -f build-Debug.ninja generated
# OR
cmake --build . --config Debug --target generated
这将构建 generator 的 Debug 配置,该配置用于生成 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 的 Debug 配置。这对于在运行生成器工具的性能优化版本(Release)的同时,构建由生成代码构成的调试版本(Debug)的目标非常有用。
自定义命令¶
在 3.20 版本中添加。
Ninja Multi-Config 生成器通过其跨配置模式为 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 是在 Debug 输出配置下使用 Release 命令配置构建的。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,第一个和第二个自定义命令会运行,因为它们的副产品(byproducts)是按配置唯一的,但最后一个自定义命令不会运行。然而,如果您在 build-Release.ninja 中构建 exe:Release,则所有三个自定义命令都会运行。