Makefile: dependencies on directory content when creating a tar file
In my battle against .PHONY
targets I re-wrote:
# Makefile v0
tar:
tar -cf tarfile.tar dir
.PHONY: tar
to be:
# Makefile v1
tar: tarfile.tar
tarfile.tar: $(shell find dir)
tar -cf $@ dir
.PHONY: tar
Which seems to work for a toy example.
However, I can see that this might do the wrong thing, depending on the time when $(shell find dir)
is evaluated开发者_如何学JAVA. If there is some rule that will create or delete files in dir
after the Makefile is parsed, this might break.
Update
Based on @user562374's answer, I seem to have a better solution, but consider this case:
# 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
Now suppose src/a
has been changed. Since there is no dependency between tarfile.tar
and dir/a
(not direct nor indirect), the tarfile.tar:
target might be evaluated before dir/a:
, and thus tarfile.tar
will not be up-to-date.
So, my questions are: What is the best practice of dealing with such cases? Must I maintain the list of files in dir
separately? If so what is the easiest way of doing it?
That is how I would use it.
.PHONY: .FORCE
.FORCE:
dirstamp: .FORCE
hxdirstamp subdir/ >$@.tmp; \
cmp -s $@ $@.tmp || mv $@.tmp $@; \
rm -f $@.tmp;
my.tar: dirstamp
tar -cf $@ subdir/;
You can also use ls -Rl
instead for dirstamping, but be aware that it is subject to influence from the locale, permission and size changes (all of which, were it just a make dependency, would be ignored).
Why not just mark tarfile.tar
as .PHONY
when dir/
contains files newer than it?
$(if $(shell find dir -type f -newer file.tar),$(eval .PHONY: file.tar))
file.tar: ; tar cvf $@ dir/
(Maybe ! -type d
would be a tad better than -type f
, but you get the idea.)
精彩评论