2016-03-14 16 views
1

我正在嘗試編寫一個遞歸製作配方。在這個配方中,每個目標都依賴於父目錄上具有相同名稱的文件。一個最小的(非工作)例如:在父目錄下寫先決條件的遞歸製作配方

foo/.dirstamp: 
    mkdir $(dir [email protected]) 
    touch [email protected] 

.SECONDEXPANSION: 
%/.dirstamp: $$(dir $$*).dirstamp 
    mkdir $(dir [email protected]) 
    touch [email protected] 

有了這個例子,我希望make foo/bar/qux/lol/.dirstamp生成整個目錄樹(如果它不存在),觸摸沿途所有.dirstamp文件。但是,這是行不通的:

$ ls # note that there is nothing, make is meant to create the dir tree 
Makefile 
$ make --debug=v foo/bar/qux/lol/.dirstamp 
GNU Make 4.0 
[...] 
Reading makefiles... 
Reading makefile 'Makefile'... 
Updating goal targets.... 
Considering target file 'foo/bar/qux/lol/.dirstamp'. 
File 'foo/bar/qux/lol/.dirstamp' does not exist. 
Finished prerequisites of target file 'foo/bar/qux/lol/.dirstamp'. 
Must remake target 'foo/bar/qux/lol/.dirstamp'. 
make: *** No rule to make target 'foo/bar/qux/lol/.dirstamp'. Stop. 

它只要遞歸配方只需要兩次擴大,例如,make foo/bar/.dirstamp工作正常工作正常。

這怎麼可以爲任意數量的層次工作?我如何處理目標名稱和先決條件名稱的遞歸擴展?

注意:我真正的問題是我的食譜的先決條件是在根目錄 目錄不同於目標,所以我使用上面的配方複製目錄樹。我知道mkdir -p 這似乎在GNU系統中工作正常。我仍然對知道如何解決任意級別的遞歸問題感興趣。 由於部分團隊正在使用Mac並將這些目錄掛載在smb上,因此它們不再有效。

有關實際問題的更多詳細信息:先決條件在data/x/y/z而目標進入results/x/y/z。但是,results目錄樹不存在,需要根據需要創建。爲了解決這個問題,我創建了父目錄作爲訂單唯一的先決條件(通過上面我最小例子中的.dirstamp文件)。

  • 無法將data複製到results,這是幾TB的數據;
  • 不能在data中創建目標,這是隻讀;
  • 不能使用mkdir -p,因爲results目錄不會是本地的,掛載在smb上,而其他的可能會使用非GNU系統;
+1

你願意使用遞歸煉成的?[陰險音樂] – Beta

+1

make不會多次應用規則。這是一種內置(有意)的限制。如果不用手動遞歸來解決這個問題,或者手動構建一組目標並使用靜態模式規則(這可能實際上也可能不實際工作,但我不確定),但對此你沒有太多的辦法。 –

+0

@Beta這將如何工作?請注意,我使用它來創建目錄樹,這些目錄不存在,因此不能有Makefile。 – carandraug

回答

2

從@EtanReisner對這個問題的提示後:

都不會套用規則不止一次。這是一種內置(有意)的限制。如果不用手動遞歸來解決這個問題,或者手動構建一組目標並使用靜態模式規則(這可能實際上也可能不實際工作,但我不確定),但對此你沒有太多的辦法。

我的工作了此解決方案:

RESULT_DIRS := $(patsubst data/%, results/%, $(shell find data/* -type d -print)) 
DIRSTAMPS := $(addsuffix /.dirstamp, $(RESULT_DIRS)) 

results/.dirstamp: 
    mkdir $(dir [email protected]) 
    touch [email protected] 

.SECONDEXPANSION: 
$(DIRSTAMPS): $$(dir $$(patsubst %/.dirstamp, %, [email protected])).dirstamp 
    mkdir $(dir [email protected]) 
    touch [email protected] 

它將複製data目錄樹中results作爲dirstamp文件是必需的。它們是由使他們成爲其他菜譜的先決條件要求(注意|這使得他們的訂單僅先決條件):

results/%/foo.analysis: data/%/foo.data | results/%/.dirstamp 
    $(SOME_ANALYSIS_PROGRAM) $^ > [email protected]