Не соблюдена целевая зависимость Makefile

#makefile #gnu-make

#makefile #gnu-make

Вопрос:

 #!make

.PRECIOUS: a/b/c/%_pqr
a/b/c/%_pqr:
        echo $@
        touch $@

.PRECIOUS: a/b/c/%_abc
a/b/c/%_abc: a/b/c/pqr_pqr
        echo $@
        touch $@
  

Когда я запускаю первый раз, он учитывает свою зависимость:

 make a/b/c/pqr_abc -f 1.mk
echo a/b/c/pqr_pqr
a/b/c/pqr_pqr
touch a/b/c/pqr_pqr
echo a/b/c/pqr_abc
a/b/c/pqr_abc
touch a/b/c/pqr_abc
  

Но если я удалю файл «a / b / c / pqr_pqr», а затем снова запущу эту цель, это не приведет к необходимому:

 rm -f a/b/c/pqr_pqr; make a/b/c/pqr_abc -f 1.mk
make: `a/b/c/pqr_abc' is up to date.
  

Насколько я понимаю, он должен снова запустить обе цели.
Пожалуйста, кто-нибудь, помогите мне.

Ответ №1:

Обе ваши цели являются неявными и, следовательно, промежуточными. Согласно документации:

Первое отличие заключается в том, что происходит, если промежуточный файл не существует. […] Но если b является промежуточным файлом, то make можно оставить в покое. Это не будет беспокоить обновление b или конечной цели, если только какое-либо предварительное условие b не является более новым, чем эта цель, или нет какой-либо другой причины для обновления этой цели.

Следовательно, поскольку pqr_abc уже существует, а pqr_pqr является промежуточным файлом и не имеет предварительных условий (поэтому предварительные условия не изменились), он не будет восстановлен.

Согласно пониманию make, pqr_pqr необходимо будет создать только для генерации из него pqr_abc (это определение промежуточного файла), и поскольку pqr_abc уже существует, нет необходимости его регенерировать.

Если вы хотите, чтобы файл каждый раз обновлялся заново, это должно быть указано явно, чтобы он больше не считался промежуточным файлом, т.е.:

 $ cat Makefile
a/b/c/%_pqr:
        touch $@

a/b/c/%_abc: a/b/c/pqr_pqr
        touch $@

a/b/c/pqr_pqr:
  

Последняя строка определяет явную цель, но не определяет рецепт, который все равно будет вызываться из неявного правила. Обратите внимание, что она больше не будет считаться промежуточной и не будет автоматически удаляться, поэтому .PRECIOUS директивы также не нужны.

Вывод:

 $ make a/b/c/pqr_abc
touch a/b/c/pqr_pqr
touch a/b/c/pqr_abc

$ make a/b/c/pqr_abc
make: 'a/b/c/pqr_abc' is up to date.

$ rm a/b/c/pqr_pqr
$ make a/b/c/pqr_abc
touch a/b/c/pqr_pqr
touch a/b/c/pqr_abc