Make中无执行脚本的目标首次调用不评估时间戳是否为预期行为?
GNU Make依赖更新检测的异常行为疑问
背景:强制目标的定义
若规则无依赖或执行脚本(recipe),且目标文件不存在,Make会认为该目标每次运行时都已更新,这意味着所有依赖此目标的规则都会始终执行其脚本。
用户认为强制目标的前提是目标文件不存在,因此下述案例不属于强制目标场景。
Makefile示例
.PHONY: update-db-type .DEFAULT: run-only-if-env-var-updated ifeq ("$(shell echo $$DB_TYPE)","mysql") DB_TYPE := mysql else DB_TYPE := tidb endif run-only-if-env-var-updated: db_type echo "Do an expensive operation" sleep 1 touch $@ # Note that db_type is a real file. db_type: update-db-type update-db-type: echo "DB_TYPE: $(DB_TYPE)" ifneq ("$(shell cat db_type)","$(DB_TYPE)") echo "$(DB_TYPE)" > db_type endif
执行命令及输出
echo mysql > db_type DB_TYPE=mysql make # Output # echo "DB_TYPE: mysql" # DB_TYPE: mysql # echo "Do an expensive operation" # Do an expensive operation # sleep 1 # touch run-only-if-env-var-updated DB_TYPE=tidb make # Output # echo "DB_TYPE: tidb" # DB_TYPE: tidb # echo "tidb" > db_type DB_TYPE=tidb make # echo "DB_TYPE: tidb" # DB_TYPE: tidb # echo "Do an expensive operation" # Do an expensive operation # sleep 1 # touch run-only-if-env-var-updated
现象分析
可以看到,耗时操作run-only-if-env-var-updated仅在第二次执行DB_TYPE=tidb make时运行。这表明首次执行时,Make未检测到文件db_type的时间戳已更新且晚于run-only-if-env-var-updated,与预期的“Make始终比较依赖与目标时间戳来判断是否执行”不符。
若给目标db_type添加非空执行脚本,修改后的规则如下:
db_type: update-db-type echo "Running DB_TYPE"
此时首次执行DB_TYPE=tidb make时,耗时操作会按预期运行。
疑问
第一个示例(无额外echo脚本)中的行为是否为Make的预期行为?若是,是否有文档解释为何首次执行会忽略更新的时间戳?
内容的提问来源于stack exchange,提问作者merlin2011
相关产品推荐
相关产品推荐

