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_TYPECMAKE_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

指定一個 分號分隔的清單,其中包含如果未指定 :<Config> 後綴,則要在 build.ninja 中為目標建置的配置。

考慮以下範例

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

這會建置 generatorDebug 配置,這將用於產生 generated.c,這將用於建置 generatedDebug 配置。

但是,如果 CMAKE_CROSS_CONFIGS 設定為 all,而您改為執行下列命令

ninja -f build-Release.ninja generated:Debug
# OR
cmake --build . --config Release --target generated:Debug

這會建置 generatorRelease 配置,這將用於產生 generated.c,這將用於建置 generatedDebug 配置。這對於執行產生器公用程式的發行最佳化版本,同時仍使用產生的程式碼建置目標的偵錯版本很有用。

自訂命令

新增於版本 3.20。

Ninja 多配置 產生器透過其跨配置模式為 add_custom_command()add_custom_target() 新增了額外的功能。COMMANDDEPENDSWORKING_DIRECTORY 引數可以在「命令配置」(正在使用的 build-<Config>.ninja 檔案的「原生」配置)或「輸出配置」(用於評估 OUTPUTBYPRODUCTS 的配置)的上下文中進行評估。

如果 OUTPUTBYPRODUCTS 命名了一個多個配置共有的路徑(例如,它不使用任何產生器表達式),則預設情況下,所有引數都會在命令配置中評估。如果所有 OUTPUTBYPRODUCTS 路徑對每個配置都是唯一的(例如,透過使用 $<CONFIG> 產生器表達式),則預設情況下,COMMAND 的第一個引數仍然在命令配置中評估,而所有後續引數,以及 DEPENDSWORKING_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>>"
  )

假設 generatortgt1tgt2tgt3tgt4 都是可執行的目標,並假設 $<CONFIG>.txt 是在 Debug 輸出組態中使用 Release 命令組態所建置的。 generator 目標的 Release 建置會以 Debug.txt Debug Release 作為引數呼叫。此命令依賴 tgt1tgt4Release 建置,以及 tgt2tgt3Debug 建置。

目標的 PRE_BUILDPRE_LINKPOST_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,則會執行所有三個自訂命令。