Makefile с несколькими правилами вывода не восстанавливает вложенную зависимость при параллельной работе - PullRequest
1 голос
/ 28 октября 2019

У меня есть make-файл с правилом, которое выдает несколько выходных данных. Чтобы обойти проблему этого правила, которое часто запускается несколько раз при параллельном запуске, я использовал фиктивный «файл метки времени». У меня также есть правило, которое зависит от одного из выходных данных этого правила «multi-output».

Когда все это выполняется из чистого состояния, все работает нормально. Тем не менее, если источник правила множественного вывода обновляется, другое правило не запускается, пока не запустится команда Make.

Я посмотрел выходные данные отладки, но не смог выполнитьмного успехов. Похоже, что Make, возможно, кэширует старую временную метку предыдущей версии файла с несколькими выходами?

Надеюсь, что нижеприведенное описание адекватно демонстрирует проблему.

 $ cat Makefile
all: data.txt

multioutput.stamp: sourcefile.txt
        touch multioutput1.txt
        touch multioutput2.txt
        touch $@

FILES=multioutput1.txt multioutput2.txt

$(FILES): multioutput.stamp

data.txt: multioutput1.txt
        touch data.txt
 $ touch sourcefile.txt
 $ make
touch multioutput1.txt
touch multioutput2.txt
touch multioutput.stamp
touch data.txt
 $ touch sourcefile.txt  # update
 $ make  # data.txt is not updated!!
touch multioutput1.txt
touch multioutput2.txt
touch multioutput.stamp
 $ make  # except when it's run again??
touch data.txt

Что я делаю неправильноздесь, и что я должен делать вместо этого?

1 Ответ

1 голос
/ 28 октября 2019

Вы врете сделать . Не делайте этого.

Как только вы запустите рецепт правила, make проверяет, действительно ли файл был обновлен по рецепту. Если он не изменился, вам не нужно заново создавать цель, в которой файл указан как зависимость.

Здесь вы не указали рецепт для multioutput1.txt, только строка зависимости:

multioutput1.txt: multioutput.stamp

Make знает, что нет способа обновить multioutput1.txt.

Дешевое исправление

Force make для проверки зависимостипредоставив явный рецепт для multioutput1.txt. Подойдет даже пустой:

${FILES}: multioutput.stamp ;

Да, вот что означает ; - первая строка рецепта следует за той же строкой.

Лучшее исправление

Единственный способ сказать, что «этот рецепт создает два файла» - это использовать шаблонное правило. Тогда нет необходимости в multioutput.stamp.

.PHONY: all
all: data.txt

%1.txt %2.txt:
    touch $*1.txt
    touch $*2.txt

data.txt: multioutput1.txt  multioutput2.txt
    touch data.txt

Здесь $* в рецепте расширяется до того, что % соответствует строке зависимости.

Почему я сделалdata.txt зависит от обоих файлов multioutput ? Здесь я придерживался мнения, что если отсутствует либо multioutput1, либо multioutput2, нам, вероятно, следует запустить рецепт для создания обоих. YMMV.

Best Fix

YMMV, но мне не нравятся правила шаблонов. Они слишком произвольны для моих вкусов.

Мы видим, что один из multioutput1.txt и multioutput2.txt всегда будет моложе другого. Они никогда не будут иметь одинаковую временную метку, если принять во внимание современную файловую систему.

.PHONY: all
all: data.txt

multioutput2.txt: start.stamp
    touch $@
    touch multioutput2.txt

multioutput1.txt: multioutput2.txt ;

data.txt: multioutput1.txt
    touch data.txt
...