在我与.PHONY
目标的战斗中,我重写了:
# Makefile v0
tar:
tar -cf tarfile.tar dir
.PHONY: tar
是:
# Makefile v1
tar: tarfile.tar
tarfile.tar: $(shell find dir)
tar -cf $@ dir
.PHONY: tar
这似乎适用于玩具示例。
但是,我可以看到这可能是错误的,具体取决于评估$(shell find dir)
的时间。如果在解析Makefile后有一些规则会在dir
中创建或删除文件,则可能会中断。
更新
根据@ user562374的回答,我似乎有更好的解决方案,但请考虑这种情况:
# Makefile v2
tar: tarfile.tar
tarfile.tar: dir/.dirstamp
tar --create --exclude $< --file $@ $(<D)
dir/.dirstamp: .FORCE
[ ! -e $@ -o "$(find $(@D) -newer $@ -print -quit)" ] && touch $@
dir/a: src/a
cp $< $@
.FORCE:
.PHONY: .FORCE tar
现在假设src/a
已更改。由于tarfile.tar
和dir/a
之间没有依赖关系(非直接或间接),tarfile.tar:
目标可能会在dir/a:
之前进行评估,因此tarfile.tar
不会是最新的。
所以,我的问题是:处理此类案件的最佳做法是什么?我必须单独维护dir
中的文件列表吗?如果是这样,最简单的方法是什么?
答案 0 :(得分:2)
这就是我如何使用它。
.PHONY: .FORCE
.FORCE:
dirstamp: .FORCE
hxdirstamp subdir/ >$@.tmp; \
cmp -s $@ $@.tmp || mv $@.tmp $@; \
rm -f $@.tmp;
my.tar: dirstamp
tar -cf $@ subdir/;
您也可以使用ls -Rl
代替dirstamping,但要注意它受区域设置,权限和大小更改的影响(所有这些都只是一个make依赖项,会被忽略)。
答案 1 :(得分:0)
当tarfile.tar
包含比它更新的文件时,为什么不将.PHONY
标记为dir/
?
$(if $(shell find dir -type f -newer file.tar),$(eval .PHONY: file.tar))
file.tar: ; tar cvf $@ dir/
(也许! -type d
会比-type f
好一点,但你明白了。)