当规则没有配方时,Make 在第一次调用时不评估目标的时间戳是预期的行为吗?

问题描述 投票:0回答:0

关于 force targets 的 Makefile 文档说明如下:

如果规则没有先决条件或配方,并且规则的目标 是一个不存在的文件,然后 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
仅在second调用
DB_TYPE=tidb make
时运行。

这意味着,在第一次调用中,Make 没有观察到文件

db_type
的时间戳已更新,并且比文件
run-only-if-env-var-updated
更新。

请注意,这不是我期望的行为;我的心智模型是 Make 总是会将依赖项的时间戳与目标的时间戳进行比较,以确定目标是否需要运行。


现在,如果我们对 Makefile 做一个小的修改,通过给目标

db_type
一个非空的配方,如下所示,然后我们得到在第一次调用
DB_TYPE=tidb make
时运行昂贵操作的预期行为。

db_type: update-db-type
    echo "Running DB_TYPE"

第一个示例中的行为(没有额外的

echo
)是Make的预期行为吗? 如果是这样,是否有文档解释为什么在第一次执行时忽略更新的时间戳?

makefile language-lawyer gnu-make
© www.soinside.com 2019 - 2024. All rights reserved.