Ninja Multi-Config

版本 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_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 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

這將建置 generatorDebug 組態,它將用於產生 generated.c,而 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,而 generated.c 將用於建置 generatedDebug 組態。這對於在仍然建置使用產生程式碼建置的目標的偵錯版本時,執行發行最佳化版本的產生器實用程式非常有用。

自訂命令

版本 3.20 新增。

Ninja Multi-Config 產生器透過其跨組態模式為 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,則所有三個自訂命令都會執行。