Makefile: зависимости от содержимого каталога при создании файла tar - PullRequest
2 голосов
/ 12 января 2011

В моей битве против .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) оценивается. Если есть какое-то правило, которое создает или удаляет файлы в dir после разбора файла Makefile, это может нарушиться.


Обновление

Судя по ответу @ 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 отдельно? Если так, какой самый простой способ сделать это?

Ответы [ 2 ]

2 голосов
/ 12 января 2011

Я бы так и использовал.

.PHONY: .FORCE
.FORCE:

dirstamp: .FORCE
        hxdirstamp subdir/ >$@.tmp; \
        cmp -s $@ $@.tmp || mv $@.tmp $@; \
        rm -f $@.tmp;

my.tar: dirstamp
        tar -cf $@ subdir/;

Вы также можете использовать ls -Rl вместо штампа, но имейте в виду, что он подвержен влиянию изменений локали, разрешений и размеров (всеиз которых, будь это просто зависимость от make, будет проигнорировано).

0 голосов
/ 12 января 2011

Почему бы просто не пометить 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, но выполучить представление.)

...