2010-06-15 66 views
10

這是here中的一個問題的延續。問題是有一條規則從單個輸入生成多個輸出,並且該命令非常耗時,所以我們寧願避免重新計算。現在有一個額外的轉折,我們希望保留文件作爲中間文件被刪除,並且規則涉及通配符以允許參數。GNU Makefile:單個規則的多個輸出+防止中間文件被刪除


的解決方案建議是,我們建立如下規則:

file-a.out: program file.in 
    ./program file.in file-a.out file-b.out file-c.out 

file-b.out: file-a.out 
    @ 

file-c.out: file-b.out 
    @ 

然後調用make file-c.out同時創建,我們避免與並聯-j開關運行make問題。迄今爲止都很好。


問題是以下內容。由於上述解決方案在DAG中設置了一個鏈,因此make認爲它有所不同;文件file-a.outfile-b.out被視爲中間文件,並且只要file-c.out準備就緒,它們默認情況下會被刪除爲不必要的。

避免這種情況的一種方法在此處提到,它包括將file-a.outfile-b.out作爲目標.SECONDARY的依存關係添加,從而避免它們被刪除。不幸的是,這並不能解決我的問題,因爲我的規則使用通配符模式;具體而言,我的規則看上去就像這樣:

file-a-%.out: program file.in 
    ./program $* file.in file-a-$*.out file-b-$*.out file-c-$*.out 

file-b-%.out: file-a-%.out 
    @ 

file-c-%.out: file-b-%.out 
    @ 

,使人們可以通過這是包含在文件名參數,例如通過運行

make file-c-12.out 

make文檔建議是該解決方案將這些隱式規則添加到.PRECIOUS的依賴關係列表中,從而保持這些文件不被刪除。


.PRECIOUS作品的解決方案,但它也可以防止當規則失敗和文件不全被刪除這些文件。有沒有其他的方式來完成這項工作?

解決這個一劈是定義一個目標.SECONDARY與任何先決條件,即,

.SECONDARY: 

它通知make的所有文件應被視爲次級並且因此不會被刪除,除非當make被中斷或規則失敗。不幸的是,這不允許通過通配符選擇一部分規則以這種方式工作,所以我認爲這只是一種破解(儘管它很有用)。

+0

嗯,還有的先決條件有沒有幹(也就是你'使用file.in而不是文件 - %。in)。如果你從file- $ n.in創建file- $ a- $ n.out,它會變得更容易,它的方式很奇怪(make file-c-17.out file-c-18.out)會產生具有不同名稱的相同輸出,除非有一些隱藏的輸入源如時間。該規則是否可以更改爲file-a - %。out:程序文件 - %。in? – p00ya 2010-06-15 15:41:02

+0

這與問題無關。這些只是制定規則,重點在於它們包含通配符。真正的規則要複雜得多,但複雜性會掩蓋我面臨的問題。 – makesaurus 2010-06-15 15:44:20

+0

看到我的答案爲什麼它是相關的。 – p00ya 2010-06-15 15:56:03

回答

2

如果不是單個file.in,而是從包含該詞幹的先決條件文件生成輸出,即

file-a.out: program file-%.in 
    ./program file-$*.in file-a-$*.out file-b-$*.out file-c-$*.out 

那麼你就可以建立所有可能的目標列表匹配:

inputs = $(wildcard file-*.in) 
secondaries = $(patsubst file-%.in,file-a-%.out,$(inputs)) \ 
    $(patsubst file-%.in,file-b-%.out,$(inputs)) 

同樣,如果幹來源於一組有限的:

batchnos = 17 18 19 20 
batchnos = $(shell seq 17 20) 
secondaries = $(patsubst %,file-a-%.out,$(batchnos)) $(patsubst %,file-b-%.out,$(batchnos)) 

然後,只需添加爲prereqs到.SECONDARY目標

.SECONDARY: $(secondaries) 
+0

這是一個可能的解決方案,並不總是很實用。在我的情況下,離開 '.SECONDARY:' 而不是列出所有可能性更簡單。另外,它不需要在輸入文件的名稱中加入'%'。您只需將所有可能的輸出文件名稱添加到輔助列表中。 – makesaurus 2010-06-15 16:01:26

16

最簡單的東西

file-a-%.out file-b-%.out file-c-%.out: program file.in 
    ./program $* file.in file-a-$*.out file-b-$*.out file-c-$*.out 

會做你想要的。

(與多個目標模式規則比與你詢問here多個目標的正常規則不同。看到make manual野牛例子。)