Почему неявные шаблонные правила .PHONY не запускаются? - PullRequest
20 голосов
/ 22 июня 2010

У меня есть следующий рекурсивный make-файл:

.PHONY: all clean

%.subdir:
    $(MAKE) -C src $*
    $(MAKE) -C dict $*

all: all.subdir

clean: clean.subdir

и работает нормально:

$ make all
make -C src all
make[1]: Entering directory `/or-1.3.6-fix/src'
make[1]: Nothing to be done for `all'.
make[1]: Leaving directory `/or-1.3.6-fix/src'
make -C dict all
make[1]: Entering directory `/or-1.3.6-fix/dict'
make[1]: Nothing to be done for `all'.
make[1]: Leaving directory `/or-1.3.6-fix/dict'

Но было бы более логично определить %.subdir правила как фальшивые:

.PHONY: all clean all.subdir clean.subdir

и теперь перестает работать так, как я хочу:

$ make all
make: Nothing to be done for `all'.
$ make -d all
...
Updating goal targets....
Considering target file `all'.
 File `all' does not exist.
  Considering target file `all.subdir'.
   File `all.subdir' does not exist.
   Finished prerequisites of target file `all.subdir'.
  Must remake target `all.subdir'.
  Successfully remade target file `all.subdir'.
 Finished prerequisites of target file `all'.
Must remake target `all'.
Successfully remade target file `all'.
make: Nothing to be done for `all'.

Может кто-нибудь объяснить мне, почему (или даже лучше указать мне, чтобы сделать документацию)?

Ответы [ 3 ]

23 голосов
/ 23 июня 2010

Вы правы, имеет смысл определить правила subdir как PHONY.Но Make не учитывает неявные правила для целей PHONY, поэтому вам придется переписать это правило.Я предлагаю следующее:

SUBDIR_TARGETS = all.subdir clean.subdir
.PHONY: all clean $(SUBDIR_TARGETS) 

$(SUBDIR_TARGETS): %.subdir:
    $(MAKE) -C src $*
    $(MAKE) -C dict $*

all: all.subdir
clean: clean.subdir
11 голосов
/ 06 августа 2016

То, что GNU устанавливает требуемые цели, объявленные как .PHONY, должно быть явным, как уже было указано в других ответах, что также предоставило некоторые средства для этого.

В этом дополнительном ответе я хотел бы добавить альтернативу, которая, как я тестировал, сочетает в себе «фальшивое» поведение, то есть то, что цели запускаются каждый раз, независимо от того, существуют ли файлы с одинаковым именем (они игнорируются).Альтернатива выглядит следующим образом:

.PHONY: phony_explicit

phony_explicit: 

%.subdir: phony_explicit
    $(MAKE) -C src $*
    $(MAKE) -C dict $*

Она работает на предпосылке, что хотя только явные цели могут быть установлены как .PHONY, что бы ни зависело от явной ложной цели, само по себе наследует многое (насколько мне известно, все)фальшивые атрибуты.Неявная цель, т. Е. Цель сопоставления с образцом, такая как %.subdir выше, аналогична тому, как если бы она была добавлена ​​к .PHONY (что невозможно, поскольку она сама по себе не является явной), но при этом становится фальшивой благодаря своей пререквизитной лжи phony_explicit.

Это сводится к тому, что каждое правило - также неявное через сопоставление с образцом - которое имеет в своих предварительных условиях явную фальшивую цель (т. Е. Цель, добавляемую к .PHONY), через эту зависимость также выполняется в фальшивомстиль (каждый раз, безусловно, в файловой системе, ошибочно имеющей файл с совпадающим именем).

Действительно, в документации GNU упоминается FORCE target , который в некоторых версиях GNU делаетне предлагать цель .PHONY частично эмулирует поведение .PHONY.Альтернатива, представленная здесь, использует это FORCE target approuch, но поскольку используется GNU make, она также устанавливает цель FORCE как .PHONY, избегая потенциальных конфликтов с реально существующими файлами с тем же именем.

С этим решением даже

touch clean.subir; make clean.subdir

даст желаемый вызов

make -C src clean
make -C dist clean

. Что может быть потенциальным преимуществом этой альтернативы, так это то, что она не нуждается вявное объявление clean.subdir и all.subdir, но на самом деле используется неявное %.subdir сопоставление с образцом.

10 голосов
/ 22 июня 2010

Из этого раздела руководства по сборке:

Неявный поиск правил (см. Неявные правила) пропускается для целей .PHONY.Вот почему объявление цели как .PHONY полезно для производительности, даже если вы не беспокоитесь о существующем файле.

Поэтому ваши неявные цели никогда не ищутся, потому что они фальшивые.

Вы можете достичь того, что пытаетесь сделать, другим способом.Попробуйте это:

SUBDIRS := all clean
.PHONY: $(SUBDIRS)

$(SUBDIRS):
    echo $(MAKE) -C src $@
    echo $(MAKE) -C dict $@
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...