2010-06-22 28 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模式匹配。