2010-06-22 31 views
12

我有以下递归生成文件:当声明图案规则为假,则不会触发

.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'. 

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

回答

17

你是对的,将子目录规则定义为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

感谢您的好意!很好。我宁愿多认证一下,说'PHONY_TARGETS:=全部干净',然后是'.PHONY:$(PHONY_TARGETS)$(addsuffix.subdir,$(PHONY_TARGETS))' – 2010-06-25 08:59:36

+1

找到这两个冒号寻找目标/ dep如果有人感兴趣,请联系:https://www.gnu.org/software/make/manual/html_node/Static-Usage.html#Static-Usage – solstice333 2016-02-12 23:57:02

7

如果您正在使用GNU做,看到the official Make manual

提出的,是没有做任何事情,因为它没有看到任何文件,使(因为它们都是假的)。确保您的 默认 隐式目标不是假的,因此make有一些东西需要构建。

更新:从化妆手册this section

因为它知道,假目标,他们 不命名实际文件,可能是从其他文件 翻拍,使跳过 隐含规则搜索假冒 目标。

因此,您的隐式目标从不被搜索,因为它们是假的。

你可以实现你正在尝试做的另一种方式。试试这个:

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

$(SUBDIRS): 
    echo $(MAKE) -C src [email protected] 
    echo $(MAKE) -C dict [email protected] 
+0

谢谢你的回答。我已经阅读过这些文件,所以如果你指出文件中的确切引用,我可以评价你的答案。更多关于您对非假冒默认目标的建议是错误的。 – 2010-06-24 13:41:55

+0

回答已更新为关于假冒规则和隐含目标的特定部分,以及解决问题的备用方法。 – bta 2010-06-24 16:24:27

+0

谢谢,现在看起来好多了。 – 2010-06-25 08:57:03

7

这GNU做出声明为.PHONY要明确规定的指标已经在其他的答案,这也提供了一些补救措施,这已经说明。

在这个额外的答案中,我想添加一个替代方案,在我测试时结合了“假冒”行为,即每次都会触发目标,而不管同名文件是否存在(它们将被忽略)。另一种方法是这样的:

.PHONY: phony_explicit 

phony_explicit: 

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

它的工作原理的前提下,而只有明确的目标可设定为.PHONY,无论取决于因此明确的伪目标本身是继承很多(据我所知,所有的)假属性。 隐含的,即模式匹配目标,例如上面的%.subdir就好像会被添加到.PHONY(这是不可能的,因为它本身并不明确),但通过其prerequesite假冒phony_explicit变成假冒。它可以归结为每个规则 - 也通过模式匹配隐含 - 在其先决条件中具有明确的假目标(即添加到.PHONY的目标)是通过这种也以假冒风格执行的依赖性(每次,无条件地在文件系统中有一个名字相同的文件)。

事实上,GNU使文档中提到的FORCEtarget,这在GNU的一些版本不提供一个.PHONY目标部分模仿.PHONY行为。此处介绍的替代方法使用此目标approuch,但由于使用了GNU make,因此它还将FORCE目标设置为.PHONY,以避免与真正存在的同名文件发生潜在冲突。

使用该解决方案甚至

touch clean.subir; make clean.subdir 

将产生

make -C src clean 
make -C dist clean 

所需调用什么可能是这种替代的潜在亲一点是,它需要的clean.subdirall.subdir没有明确的声明,但实际上使用了隐式%.subdir模式匹配。