为什么.PHONY隐式模式规则没有被触发?

dma*_*a_k 22 makefile

我有以下递归makefile:

.PHONY: all clean

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

all: all.subdir

clean: clean.subdir
Run Code Online (Sandbox Code Playgroud)

它工作正常:

$ 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'
Run Code Online (Sandbox Code Playgroud)

但将%.subdir规则定义为虚假更合乎逻辑:

.PHONY: all clean all.subdir clean.subdir
Run Code Online (Sandbox Code Playgroud)

现在让我停止工作:

$ 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'.
Run Code Online (Sandbox Code Playgroud)

有人可以解释我为什么(甚至更好地指出我制作文档)?

Bet*_*eta 25

你是对的,将子网规则定义为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
Run Code Online (Sandbox Code Playgroud)

  • 如果有人感兴趣的话,找到两个冒号的目标/ dep线的文档:https://www.gnu.org/software/make/manual/html_node/Static-Usage.html#Static-Usage (5认同)

hum*_*ace 14

GNU使得声明为.PHONY明确的所需目标已在其他答案中说明,这也为此提供了一些补救措施.

在这个额外的答案中,我想添加一个替代品,当我测试时结合了"虚假"行为,即每次无论是否存在同名文件(都被忽略),都会触发目标.替代方案如下:

.PHONY: phony_explicit

phony_explicit: 

%.subdir: phony_explicit
    $(MAKE) -C src $*
    $(MAKE) -C dict $*
Run Code Online (Sandbox Code Playgroud)

它的工作前提是,虽然只有明确的目标可以设置为.PHONY,但是依赖于明确的伪目标的任何东西本身都会继承很多(据我所知)虚假属性.一个隐含的,即模式匹配目标,%.subdir如上所述,就好像被添加到.PHONY(这是不可能的,因为它本身不是明确的),但通过其先发制人的虚假变成虚假phony_explicit.

它归结为每个规则 - 也通过模式匹配隐含 - 在其先决条件中具有明确的虚假目标(即添加到其中的目标.PHONY)是通过这种依赖性也以虚假的方式执行(每次,无条件地文件系统错误地执行)有一个具有一个令人难以置信的名字的文件).

实际上,GNU make文档提到了FORCE 目标,在某些版本的GNU中,不提供.PHONY目标的部分模拟了.PHONY行为.此处提供的替代方法使用此FORCE目标approuch,但由于使用了GNU make,它还将FORCE目标设置为.PHONY避免与现有的同名文件发生潜在冲突.

有了这个解决方案甚至

touch clean.subir; make clean.subdir
Run Code Online (Sandbox Code Playgroud)

将产生所需的调用

make -C src clean
make -C dist clean
Run Code Online (Sandbox Code Playgroud)

可能这个替代方案的潜在优点是它不需要显式声明clean.subdirall.subdir,但实际上是使用隐式%.subdir模式匹配.


bta*_*bta 10

从制作手册的这一部分:

对于.PHONY目标,将跳过隐式规则搜索(请参阅隐式规则).这就是为什么将目标声明为.PHONY有利于提高性能,即使您不担心实际存在的文件.

因此,永远不会搜索您的隐式目标,因为它们是虚假的.

你可以通过另一种方式实现你想做的事情.试试这个:

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

$(SUBDIRS):
    echo $(MAKE) -C src $@
    echo $(MAKE) -C dict $@
Run Code Online (Sandbox Code Playgroud)