2016-07-29 33 views
0

我想要一個規則表現爲一個函數,例如可以gzip所有我的臨時目標。我寫這些規則在makefile:將gnu-make規則作​​爲函數應用

%.file0:    
     touch [email protected]  

%.file1: %  
     touch [email protected]  

%.file2: %   
     touch [email protected]  

%.gz: %  
     echo "zipping to [email protected]" 
     touch [email protected] 

我可以叫

$ make -n dotted.file.file0.file1.file2.gz -f makefile 
touch dotted.file.file0 
touch dotted.file.file0.file1 
touch dotted.file.file0.file1.file2 
echo "zipping to dotted.file.file0.file1.file2.gz" 
rm dotted.file.file0 dotted.file.file0.file1.file2 dotted.file.file0.file1 

我最後的目標將順利gzip壓縮。那麼我可以前gzip壓縮dotted.file.file0.file1:

$ make -n dotted.file.file0.file1.gz.file2 -f makefile 
touch dotted.file.file0             
touch dotted.file.file0.file1            
echo "zipping to dotted.file.file0.file1.gz"        
touch dotted.file.file0.file1.gz.file2          
rm dotted.file.file0 dotted.file.file0.file1.gz dotted.file.file0.file1 

這個文件會也正在給予規則%.file2之前用gzip壓縮。但我不能gzip幾個目標:

$ make -n dotted.file.file0.file1.gz.file2.gz -f makefile 
make: *** No rule to make target `dotted.file.file0.file1.gz.file2.gz'. Stop. 

我該怎麼做,即應用%.gz規則在幾個目標上?


編輯1

從另一個角度來看,我試圖重寫我的規則是這樣的:

%.file0:      
     touch [email protected]    

%.file1: %.gz    
     touch [email protected]    

%.file2: %.gz    
     touch [email protected]    

%.gz: %      
     echo "zipping to [email protected]" 
     touch [email protected] 

然後我打電話讓:

$ make -n dotted.file.file0.file1.file2 -f makefile 
make: *** No rule to make target `dotted.file.file0.file1.file2'. Stop. 

我希望/心願gnu-make執行這條命令的規則:

- ask for the file dotted.file.file0.file1.file2 
- go to rule %.file2 
- ask for the dependency dotted.file.file0.file1.gz 
- go to rule %.gz 
- as for the dependency dotted.file.file0.file1 
- go to rule %.file1 
- as for the dependency dotted.file.file0.gz 
- go to rule %.gz 
- as for the dependency dotted.file.file0 
- go to rule %.file0 
- create file dotted.file.file0 

但是,如果我只要求一個規則來應用%.gz,它將在單一時間內工作。

生成文件:

%.file0:      
     touch [email protected]    

%.file1: %.gz # !!! Notice I left this single dependency to the rule %.gz   
     touch [email protected]    

%.file2: % ## !!! Notice I removed the .gz here    
     touch [email protected]    

%.gz: %      
     echo "zipping to [email protected]" 
     touch [email protected] 

命令:

$make -n dotted.file.file0.file1.file2 -f makefile 
touch dotted.file.file0      
touch dotted.file.file0.file1      
echo "zipping to dotted.file.file0.file1.gz"   
touch dotted.file.file0.file1.gz      
touch dotted.file.file0.file1.file2      
rm dotted.file.file0.file1.gz dotted.file.file0 dotted.file.file0.file1 
+0

是否有某些原因需要這些複合文件名(例如'bar.file0.file1.file2'而不是'bar.file2')? – Beta

+0

唯一的重點是跟蹤哪些步驟(規則)已應用於文件,這是提供信息。這就是爲什麼不會使用相同的規則兩次? – kaligne

+0

你在問這個問題。建立'bar.file0.file1。file2'大概可以用一些努力和聰明來完成;建立'bar.file2'要容易得多,而且名字傳達的信息完全相同。 – Beta

回答

0

與你的第一個版本的問題是,你需要靜態模式規則,沒有潛規則。以下是GNU make的工作,使用shell調用awk從指定的make目標構建顯式列表*.file1,*.file2*.gz目標。它還使用foreach-eval-call組合來根據需要實例化許多規則(無配方)以明確表示所有依賴關係。我必須承認,這種風格的Makefile是相當不尋常的,但你的問題是不尋常的太...

SUFFIXES := file1 file2 gz 

# For goal $(1) and suffix $(2), build the list of all possible stems <S> such 
# that $(1) matches the ^<S>\.$(2)(\..*)? regular expression. Concatenate this 
# list to the $(2) make variable. 
define SPLIT_rule 
$(2) += $$(shell echo $(1) | awk -F.$(2) '{for(i=1;i<=NF;i++){for(j=1;j<=i;j++)printf("%s",$$$$j);printf(".$(2) ")}}') 
endef 

# For goal $(1), instantiate SPLIT_rule for each suffix. 
define GOAL_rule 
$(foreach suffix,$(SUFFIXES),$(eval $(call SPLIT_rule,$(1),$(suffix)))) 
endef 

$(foreach goal,$(MAKECMDGOALS),$(eval $(call GOAL_rule,$(goal)))) 

# For suffix $(1), instantiate the static pattern rule. 
define SUFFIX_rule 
$$($(1)): %.$(1): % 
endef 

$(foreach suffix,$(SUFFIXES),$(eval $(call SUFFIX_rule,$(suffix)))) 

%.file0: 
    touch [email protected] 

%.file1: % 
    touch [email protected] 

%.file2: % 
    touch [email protected] 

%.gz: % 
    echo "zipping to [email protected]" 
    touch [email protected] 

和:

$ goal1=dotted.file.file0.file1.file2.gz 
$ make -n $goal1 
touch dotted.file.file0 
touch dotted.file.file0.file1 
touch dotted.file.file0.file1.file2 
echo "zipping to dotted.file.file0.file1.file2.gz" 
touch dotted.file.file0.file1.file2.gz 

$ goal2=dotted.file.file0.file1.gz.file2 
$ make -n $goal2 
touch dotted.file.file0 
touch dotted.file.file0.file1 
echo "zipping to dotted.file.file0.file1.gz" 
touch dotted.file.file0.file1.gz 
touch dotted.file.file0.file1.gz.file2 

$ goal3=dotted.file.file0.file1.gz.file2.gz 
$ make -n $goal3 
touch dotted.file.file0 
touch dotted.file.file0.file1 
echo "zipping to dotted.file.file0.file1.gz" 
touch dotted.file.file0.file1.gz 
touch dotted.file.file0.file1.gz.file2 
echo "zipping to dotted.file.file0.file1.gz.file2.gz" 
touch dotted.file.file0.file1.gz.file2.gz 

$ goal4=dotted.file.file0.file1.file2 
$ make -n $goal4 
touch dotted.file.file0 
touch dotted.file.file0.file1 
touch dotted.file.file0.file1.file2 

$ all="$goal1 $goal2 $goal3 $goal4" 
$ make -n $all 
touch dotted.file.file0 
touch dotted.file.file0.file1 
touch dotted.file.file0.file1.file2 
echo "zipping to dotted.file.file0.file1.file2.gz" 
touch dotted.file.file0.file1.file2.gz 
echo "zipping to dotted.file.file0.file1.gz" 
touch dotted.file.file0.file1.gz 
touch dotted.file.file0.file1.gz.file2 
echo "zipping to dotted.file.file0.file1.gz.file2.gz" 
touch dotted.file.file0.file1.gz.file2.gz 
make: 'dotted.file.file0.file1.file2' is up to date. 

注:所有中間體都沒有任何隱含的更多,他們不自動刪除,就像他們在第一個版本中被宣佈爲PRECIOUS一樣。這就是爲什麼在輸出中不再有rm ...的原因。