我缺少一些可能平凡但关键的理解,即 make 如何确定是否必须构建依赖项。我已将问题归结为一个非常简单的示例。
build:
mkdir -p $@
.PRECIOUS: build/%.txt
build/%.txt: build
@echo "$*" > $@
%.zip: %.txt
zip -jquX $@ $<
我觉得第一次运行 make build/foo.zip
应该首先创建“build”目录,然后写入“build/foo.txt”,最后构建“build/foo.zip” ” 留下“build/foo.txt”。然后,所有连续运行都应该没有任何事情可做,因为没有依赖项比依赖它们的目标更新。
但是,我得到以下输出:
➜ make build/f.zip
mkdir -p build
zip -jquX build/f.zip build/f.txt
➜ make build/f.zip
zip -jquX build/f.zip build/f.txt
➜ make build/f.zip
make: 'build/f.zip' is up to date.
如何避免这种情况?是什么导致第二个 zip 操作不被跳过?
更多信息
我在 Antergos 上使用 GNU Make 4.2.1,并在 VirtualBox 中使用 ext4 文件系统。
最佳答案
在 @o11c 的大力推荐下,我想出了解决方案。事实证明这是有记录的行为。将文件添加到目录时,目录的时间会更新。第二次运行时不会发生这种情况,因为没有文件写入该文件夹。
根据 prerequisite types 的文档:
Consider an example where your targets are to be placed in a separate directory, and that directory might not exist before make is run. In this situation, you want the directory to be created before any targets are placed into it but, because the timestamps on directories change whenever a file is added, removed, or renamed, we certainly don’t want to rebuild all the targets whenever the directory’s timestamp changes. One way to manage this is with order-only prerequisites: make the directory an order-only prerequisite on all the targets.
这是可行的解决方案。需要添加的只是 |
。
build:
mkdir -p $@
.PRECIOUS: build/%.txt
build/%.txt: | build
@echo "$*" > $@
%.zip: %.txt
zip -jquX $@ $<
关于makefile - GNU Make 目标在 "up to date"之前构建了两次;为什么不在第一遍之后呢?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51575707/