如何依赖哈希,即始终执行哈希计算,但只有在发生变化时才重建?

How to depend on a hash, i.e. always execute hash calculation, but only rebuild if it changed?

我只想要一个昂贵的食谱 运行 当有一个文件被添加或删除时。为了生成哈希,我基本上使用了 find dir -name '*.cpp' | git hash-object --stdin,因为文件的内容在那一步并不重要。

我试过了:

# forcing to always calculate the hash
.PHONY: calc_hash
calc_hash:
    do_find_and_update_fileshash_only_if_different.sh

# depend on the calc_hash without automatically be out-of-date
files.hash: | calc_hash

someothertarget: files.hash
   <some recipe>

脚本仅在旧哈希值 != 新哈希值时写入。尽管如此,在更改之后,someothertarget 起初不会重建,然后在第二次调用时会重建。看起来脚本所做的 files.hash 更改尚未在同一 运行.

中考虑

Windows 使用 mingw32-make 如果重要的话。不使用脚本会很好,但也没有让它工作。 Compare this,但它使用始终计算的变量,我不喜欢这样。

不确定当一个虚假目标也是另一个目标的仅订单先决条件时会发生什么,但这有点不寻常。如果您的 do... 脚本仅在某些内容发生变化时修改 files.hash,您可以尝试以下操作:

someothertarget: files.hash
    <some recipe>

files.hash: FORCE
    do_find_and_update_fileshash_only_if_different.sh

.PHONY: FORCE

因为files.hash不是假的someothertarget不会被系统地重建,make会考虑它的最后修改时间。但由于 FORCE 是假的,make 将始终尝试重建 files.hash.

诀窍是避免昂贵的目标直接依赖于伪造的目标,因为它会被系统地重建。相反,我们可以使用间接依赖。当然,只有当我们需要重建代价高昂的目标时,中间目标才必须通过其配方进行修改。

所有这些都可以很容易地进行测试,例如:

$ cat Makefile
CHANGE := NO

costly: changed
    @echo "building $@"
    @touch $@

changed: FORCE
    @echo "do we need to build $@?"
    @if ! [ -f "$@" ] || [ "$(CHANGE)" = "yes" ]; then \
        echo "  yes, building $@"; \
        touch "$@"; \
    else \
        echo "  no, not building $@"; \
    fi

.PHONY: FORCE

$ rm -f changed costly
$ make
do we need to build changed?
  yes, building changed
building costly
$ make
do we need to build changed?
  no, not building changed
$ make CHANGE=yes
do we need to build changed?
  yes, building changed
building costly