Makefile 为什么不触发虚假的隐式模式规则?
我有以下递归生成文件:Makefile 为什么不触发虚假的隐式模式规则?,makefile,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'. mak
.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'
但将%定义为虚假规则更符合逻辑:
.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'.
有人能给我解释一下原因吗(或者更好地告诉我制作文档)?来自制作手册:
将跳过.PHONY目标的隐式规则搜索(请参见隐式规则)。这就是为什么将目标声明为.PHONY对性能有好处,即使您不担心实际存在的文件
因此,您的隐式目标永远不会被搜索,因为它们是假的
你可以通过另一种方式实现你想做的事情。试试这个:
SUBDIRS := all clean
.PHONY: $(SUBDIRS)
$(SUBDIRS):
echo $(MAKE) -C src $@
echo $(MAKE) -C dict $@
你说得对,将细分规则定义为虚假规则更有意义。但不考虑伪目标的隐式规则,所以必须改写该规则。我建议如下:
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
GNU将要求的目标声明为.PHONY
明确,这一点在其他答案中已经说明,这也提供了一些补救措施
在这个附加答案中,我想添加一个替代选项,在我测试时,它结合了“虚假”行为,即无论是否存在同名文件(它们被忽略),每次都会触发目标。另一种选择是:
.PHONY: phony_explicit
phony_explicit:
%.subdir: phony_explicit
$(MAKE) -C src $*
$(MAKE) -C dict $*
它工作的前提是,虽然只有显式目标可以设置为.PHONY,但依赖于显式虚假目标的任何东西本身都继承了很多(据我所知)虚假属性。
一个隐式的,即模式匹配目标,如上面的%.subdir
,就像将其添加到.PHONY
(这是不可能的,因为它本身不是显式的),但通过其prerequesite PHONYPHONY_explicit
,它却变得虚假
归根结底,每一条规则——也是通过模式匹配隐式的——其先决条件中都有一个显式的虚假目标(即添加到.phony
)的目标——都是通过这种依赖关系以虚假的方式执行的(每次,无条件地,文件系统错误地拥有一个同名文件)
事实上,GNU make文档提到了强制力
,在一些不提供.PHONY
目标的GNU版本中,它部分模拟了.PHONY
行为。这里介绍的替代方法使用此FORCE
target方法,但由于使用了GNU make,因此它还将FORCE
target设置为.PHONY
,以避免与同名的实际存在的文件发生潜在冲突
使用此解决方案,即使是
touch clean.subir; make clean.subdir
将产生所需的
make -C src clean
make -C dist clean
此替代方案的潜在优点是,它不需要明确声明clean.subdir
和all.subdir
,而是使用隐式%.subdir
模式匹配。谢谢您的回答。我已经读过文档,所以如果你给我指出文档中的确切引用,我可以给你的答案打分。关于非虚假默认目标的更多建议是错误的。答案已更新,其中包含关于虚假规则和隐式目标的特定部分,以及解决问题的另一种方法。谢谢,现在看起来好多了。谢谢你的提示!很好。我宁愿稍微修饰一下,然后说PHONY_TARGETS:=all clean
。PHONY:$(PHONY_TARGETS)$(addsuffix.subdir,$(PHONY_TARGETS))
找到了两个冒号目标/dep行的文档,如果有人感兴趣的话: