CMP0058

警告

此政策的 OLD 行為已在 CMake 4.0 版本中移除。此政策必須透過呼叫 cmake_minimum_required()cmake_policy() 設定為 NEW

在版本 3.3 中新增。

Ninja 要求自訂命令的副產品必須明確宣告。

當建置期間產生的中繼檔案被耗時的操作或龐大的依賴樹狀結構使用時,可以透過僅在檔案內容變更時才更新檔案時間戳記,來減少增量重建所需的工作。使用這種方法,產生規則必須有一個獨立的輸出檔案,該檔案始終以比規則的任何依賴項更新的時間戳記進行更新,以便建置工具僅在輸入變更時才重新執行該規則。我們將這個獨立的輸出檔案稱為規則的見證(witness),將產生的檔案稱為規則的副產品(byproduct)。

副產品可能不會被列為輸出,因為它們的時間戳記可能比輸入舊。在 CMake 設計時存在的任何建置工具(如 make)都沒有辦法表達副產品。因此,CMake 3.2 之前的版本沒有辦法指定它們。專案通常將副產品留在產生它們的規則中未宣告。例如:

add_custom_command(
  OUTPUT witness.txt
  COMMAND ${CMAKE_COMMAND} -E copy_if_different
          ${CMAKE_CURRENT_SOURCE_DIR}/input.txt
          byproduct.txt # timestamp may not change
  COMMAND ${CMAKE_COMMAND} -E touch witness.txt
  DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/input.txt
  )
add_custom_target(Provider DEPENDS witness.txt)
add_custom_command(
  OUTPUT generated.c
  COMMAND expensive-task -i byproduct.txt -o generated.c
  DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/byproduct.txt
  )
add_library(Consumer generated.c)
add_dependencies(Consumer Provider)

這對於除了 Ninja 之外的所有產生器都運作良好。Ninja 建置工具將規則中列出的 byproduct.txt 視為依賴項,但沒有規則將其列為輸出。然後 Ninja 會抱怨沒有辦法滿足這個依賴項,並停止建置,即使有僅限順序的依賴關係確保 byproduct.txt 會在其消費者需要它之前存在。有關 Ninja 為何這樣運作的更多詳細資訊,請參閱 Ninja Issue 760 中對此問題的討論。

Ninja 期望將副產品與其他輸出一起列出,而不是將副產品留在產生它們的規則中未宣告。這樣的規則可以使用 restat 選項標記,該選項告訴 Ninja 在規則執行後檢查輸出的時間戳記。這可以防止時間戳記沒有變更的副產品不必要地導致其依賴項重新建置。

由於上述方法沒有告訴 CMake 哪個自訂命令產生 byproduct.txt,因此 Ninja 產生器沒有足夠的資訊將副產品新增為任何規則的輸出。CMake 2.8.12 及更高版本繞過了這個問題,並允許使用上述方法的專案透過產生 phony 建置規則來告訴 Ninja 容忍此類遺失的檔案來進行建置。然而,這種變通方法阻止了 Ninja 診斷出真正遺失的依賴項。它在來源內建置中也運作不佳,因為 CMake 沒有足夠的資訊來知道哪些檔案是作為自訂命令的副產品產生的,因此即使是對來源檔案的每個自訂命令依賴項都需要以這種方式處理。

引入副產品

CMake 3.2 為 add_custom_command()add_custom_target() 命令引入了 BYPRODUCTS 選項。此選項允許明確指定副產品:

add_custom_command(
  OUTPUT witness.txt
  BYPRODUCTS byproduct.txt # explicit byproduct specification
  COMMAND ${CMAKE_COMMAND} -E copy_if_different
          ${CMAKE_CURRENT_SOURCE_DIR}/input.txt
          byproduct.txt # timestamp may not change
...

BYPRODUCTS 選項被 Ninja 產生器用於列出自訂命令的輸出中的副產品,並被其他產生器忽略。

CMake 3.3 及更高版本傾向於要求專案明確指定自訂命令的副產品,以便它可以完全避免使用 phony 規則變通方法。引入政策 CMP0058 是為了提供與仍然需要變通方法的現有專案的相容性。

此政策對 Ninja 以外的產生器沒有影響。此政策的 OLD 行為是為建置樹狀結構中未知的依賴項產生 Ninja phony 規則。NEW 行為是不產生這些規則,而是要求專案明確指定自訂命令 BYPRODUCTS

政策設定必須在專案頂層 CMakeLists.txt 檔案的結尾範圍內,並具有全域效果。

此政策在 CMake 3.3 版本中引入。在 CMake 4.0 版本中移除之前,它可以透過 cmake_policy()cmake_minimum_required() 進行設定。如果未設定,CMake 在看到來源外部建置樹狀結構中未知的依賴項時會發出警告,並使用 OLD 行為。