2013-03-21 52 views
0

我有一堆C文件在不同的目錄中,我得到一個make: nothing to be done for 'all'錯誤與我的遞歸Makefile;但是,如果我調整依賴性,我可以讓它工作......但我不明白爲什麼我必須這樣做。遞歸makefile不構建

這是我原來的Makefile:

APP_DIRS=rescoco ressys resvm 

.PHONY: all 

all: $(APP_DIRS) 

$(APP_DIRS): 
    $(MAKE) --directory [email protected] 

clean: 
    $(RM) *~ 

現在,如果我改變我的路線:.PHONY.PHONY: all $(APP_DIRS)它建立的罰款。

另一種可能性是,如果我更改該行:$(APP_DIRS):$(APP_DIRS): clean它可以正常工作。

(注:在卸下.PHONY目標不會改變任何東西)


那麼是什麼回事? Makefile試圖告訴我我沒有正確列出依賴項?我想make會做這樣的事情:

  • 打造.PHONY我首先要建立all
  • 打造all我首先要建立$(APP_DIRS)
  • $(APP_DIRS)已經沒有prereqs所以對於執行命令(這會導致遞歸運行)。

顯然我錯了;但爲什麼?


僅供參考,如果它的事項我的文件結構是這樣的:

Makefile  #top level makefile as seen above 
/rescoco 
    rescoco.c 
    Makefile #builds rescoco src and moves archive to ../lib directory 
/ressys 
    ressys.c 
    Makefile #same as above but for ressys 
/resvm 
    resvm.c 
    Makefile #same as above but for resvm 
/lib 

和我的生成命令簡直是make。當我與make -nmake -n all跑我得到任何輸出:

:~/proj$ make -n all 
make: Nothing to be done for 'all'. 
:~/proj$ 
+0

你使用了什麼命令?使所有? – 75inchpianist 2013-03-21 17:44:07

+0

運行make -n查看到底發生了什麼。我也使用變量打印來確保一切正常。 – stdcall 2013-03-21 17:45:24

+0

@ 75inchpianist - 只是'make',但'make all'會給出相同的結果。 (見編輯) – Mike 2013-03-21 17:50:37

回答

2

件事首先,你應該知道的:

  • 如果你有目錄的依賴關係,使得將要考慮建設目標(即執行這些目錄目標的配方),只有當目錄的修改時間戳得到更新時。 只有在目錄中添加新文件但不包含目錄中的文件修改時纔會發生這種情況。在子目錄中添加文件不會更改目錄的時間戳。
  • PHONY目標是用來執行這樣一個目標不會創建一個文件的目標名稱。換句話說,無論文件是否已經存在,您都希望執行規則。

所以你的Makefile esentially只告訴這個:

  • 構建目標all,我需要建立$(APP_DIRS)。由於all是PHONY目標,因此我將始終執行all的配方。
  • $(APP_DIRS)不是PHONY目標,並且沒有任何依賴關係。所以*只有當$(APP_DIRS)已經不存在(即文件或目錄)時,我纔會執行配方,否則我對這個目標什麼都不做。
  • clean沒有先決條件,也沒有PHONY,所以我希望只有在make(從命令行或另一個Makefile)顯式調用時才執行此規則。此外clean不是PHONY,所以我期望的配方中創建一個名爲執行後clean(這是不正確你的情況下)

因此改變.PHONY行文件:

.PHONY: all $(APP_DIRS) 

使Makefile始終執行$(APP_DIRS)的配方。

所以,如果你想使總是遍歷到所有$(APP_DIRS)的目錄,並在他們身上再次調用做,你需要添加$(APP_DIRS).PHONY,這使得$(APP_DIRS)假目標,並執行不管文件的/目錄的時間戳是否存在

您的特定用例,我覺得這是你應該使用的Makefile:

APP_DIRS=rescoco ressys resvm 

.PHONY: all clean $(APP_DIRS) 

all: $(APP_DIRS) 

$(APP_DIRS): 
    $(MAKE) --directory [email protected] 

clean: 
    $(RM) *~ 

獎金:

  • 更改$(APP_DIRS):$(APP_DIRS): clean意味着$(APP_DIRS)依賴於clean目標。
  • 儘管clean未標記爲PHONY,但make在當前目錄中看不到名爲clean的文件。所以它繼續並嘗試執行clean的配方。
  • 由於建立了$(APP_DIRS)(即clean)的依賴關係,所以這使得Makefile執行構建$(APP_DIRS)的配方。

這給我們帶來了一個有趣的觀察: - 任何依賴於PHONY目標的目標都將被重建(即配方將被執行)。

拿這個簡單的Makefile:

all: target1 

target1: target2 
    @echo "[email protected]" 
    @touch [email protected] 

target2: target3 
    @echo "[email protected]" 
    @touch [email protected] 

target3: 
    @echo "[email protected]" 

.PHONY: all target3 

我第一次跑make,我看到這樣的輸出:

target3 
target2 
target1 

在此之後,target1target2創建文件。即使這樣,如果我再次運行make,我會看到輸出:

target3 
target2 
target1 

正如你所看到的,PHONY依賴關係得到傳播並沒有下降的其他方式。 target2因爲target3是PHONY而重建,target1因爲target2重建而重建。

+0

+1好吧,這很有道理。我知道,如果某件事被列爲'.PHONY',它總是會被構建的,我認爲這意味着如果我將'all'列爲'.PHONY',它的所有依賴關係總是會被建立...但不會傳播。正確? – Mike 2013-03-21 18:31:39

+0

@Mike - 'PHONY'依賴關係在依賴鏈中傳播,而不是相反。看看我在最後添加的例子。 – Tuxdude 2013-03-21 19:45:44

0

您正在使用目錄列表定義一個名爲'APP_DIRS'的變量。沒事兒。

你再做

$(APP_DIRS): make blah blah,這基本上等同於rescoco ressys resvm: make blah blah

這顯然心不是有效的。

所以你需要假裝你的$(APP_DIRS)是一個變量,而不是目標名稱,這似乎是你使用它的。

話說回來,覺得爲什麼.PHONY:所有$(APP_DIRS)的作品