开发者

Makefile: dependencies on directory content when creating a tar file

开发者 https://www.devze.com 2023-02-04 08:11 出处:网络
In my battle against .PHONY targets I re-wrote: # Makefile v0 tar: tar -cf tarfile.tar dir .PHONY: tar to be:

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.)

0

精彩评论

暂无评论...
验证码 换一张
取 消