CMP0058¶
警告
此策略的 OLD
行为已在 CMake 4.0 版本中移除。此策略必须通过调用 cmake_minimum_required()
或 cmake_policy()
设置为 NEW
。
在版本 3.3 中添加。
Ninja 要求自定义命令的副产品必须是显式的。
当构建期间生成的中间文件被昂贵的操作或大型依赖树消耗时,可以通过仅在文件内容更改时更新文件时间戳来减少增量重建所需的工作。使用这种方法,生成规则必须有一个单独的输出文件,该文件始终使用比规则的任何依赖项更新的时间戳进行更新,以便构建工具仅在输入更改时重新运行规则。我们将单独的输出文件称为规则的见证,并将生成的文件称为规则的副产品。
副产品可能不会被列为输出,因为它们的时间戳可能比输入旧。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 引入了 BYPRODUCTS
选项到 add_custom_command()
和 add_custom_target()
命令。此选项允许显式指定副产品
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
...
Ninja
生成器使用 BYPRODUCTS
选项在生成它们的自定义命令的输出中列出副产品,其他生成器会忽略它。
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
行为。