我有以下递归makefile:
.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'.
有人可以解释一下为什么(或者更好地指出我制作文档)?
答案 0 :(得分:22)
你是对的,将子网规则定义为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
答案 1 :(得分:9)
来自制作手册的this section:
为.PHONY目标跳过隐式规则搜索(请参阅隐式规则)。这就是为什么将目标声明为.PHONY有利于提高性能,即使您不担心实际存在的文件。
因此,永远不会搜索隐式目标,因为它们是虚假的。
您可以通过其他方式实现您想要做的事情。试试这个:
SUBDIRS := all clean
.PHONY: $(SUBDIRS)
$(SUBDIRS):
echo $(MAKE) -C src $@
echo $(MAKE) -C dict $@
答案 2 :(得分:9)
GNU使得声明为.PHONY
的必需目标明确已经在其他答案中说明,这也为此提供了一些补救措施。
在这个额外的答案中,我想添加一个替代品,当我测试时结合了“虚假”行为,即每次无论是否存在同名文件(都被忽略),都会触发目标。替代方案如下:
.PHONY: phony_explicit
phony_explicit:
%.subdir: phony_explicit
$(MAKE) -C src $*
$(MAKE) -C dict $*
它的前提是,虽然只有明确的目标可以设置为.PHONY,但是依赖于明确的伪目标的任何东西本身都会继承很多(据我所知)虚假属性。
一个隐式的,即模式匹配目标,例如上面的%.subdir
,就好像被添加到.PHONY
一样(这是不可能的,因为它本身并不是明确的),但是通过它的先天假的虚假变成了假的{{ 1}}。
归结为每个规则 - 也通过模式匹配隐含 - 在其先决条件中具有明确的虚假目标(即添加到phony_explicit
的目标)是通过这种依赖也以虚假的方式执行(每次,无条件地文件系统错误地拥有一个具有恰好名称的文件)。
实际上,GNU make文档提到了.PHONY
target,在某些版本的GNU中,不提供FORCE
目标会部分模仿.PHONY
行为。此处提供的替代方法使用此.PHONY
目标approuch,但由于使用了GNU make,它还将FORCE
目标设置为FORCE
,以避免与实际存在的同名文件发生潜在冲突。
使用此解决方案甚至
.PHONY
将产生所需的
调用touch clean.subir; make clean.subdir
这个替代方案的潜在优点是它不需要明确声明make -C src clean
make -C dist clean
和clean.subdir
,但实际上是使用隐式all.subdir
模式匹配。