makefile筆記(2)

isstack發表於2017-09-01

書寫規則


  • 規則包含兩部分,一是依賴關係,一是生成目標的方法。

     makefile中規則的順序很重要,因為makefile中只有一個最終目標,這個目標一定要解除安裝第一個。
     基本規則就是 :

  目標 :對應的依賴
      命令
  • makefile中的萬用字元

makefile支援三個萬用字元:“*”,“?”,“[ … ]”。波浪號(“~”)在檔案命中有比較特殊的用途。eg:“~/test”,表示當前使用者的$HOME目錄下的text目錄。“~isstack/test”表示在使用者isstack的宿主目錄下的test目錄。windows下使用者沒有宿主目錄,則都指環境變數“HOME”。
 * 指匹配所有字元,如 *.c 匹配所有c檔案。* 可以用在命令中和shell一樣,也可以用在規則中,同樣可以用在變數中,eg:
 

objects = *.o  

 但是並不是說定義的時候就會直接展開獲得所有.o 檔案,objects的值就是“*.o” ,相當於C中的巨集,若想要萬用字元在變數中就展開,可以:
 

 objects := $(wildcard *.o)   

   wildcard是makefile的關鍵字。
 


  • 檔案搜尋

在一些大的工程中,有大量的原始檔,我們通常的做法是把這許多的原始檔分類,並存
放在不同的目錄中。所以,當 make 需要去找尋檔案的依賴關係時,你可以在檔案前加上路
徑,但最好的方法是把一個路徑告訴 make,讓make 在自動去找。

Makefile 檔案中的特殊變數“VPATH”就是完成這個功能的,如果沒有指明這個變數,
make 只會在當前的目錄中去找尋依賴檔案和目標檔案。如果定義了這個變數,那麼,make
就會在噹噹前目錄找不到的情況下,到所指定的目錄中去找尋檔案了。

VPATH = src:../headers   

上面的的定義指定兩個目錄,“src”和“../headers”,make 會按照這個順序進行搜 索。目錄由“冒號”分隔。(當然,當前目錄永遠是最高優先搜尋的地方)

 另一個設定檔案搜尋路徑的方法是使用 make 的“vpath”關鍵字(注意,它是全小寫 的),這不是變數,這是一個 make 的關鍵字,這和上面提到的那個 VPATH 變數很類似,但是 它更為靈活。它可以指定不同的檔案在不同的搜尋目錄中。這是一個很靈活的功能。它的使
用方法有三種:

1、vpath
 為符合模式的檔案指定搜尋目錄。

2、vpath
 清除符合模式的檔案的搜尋目錄。

3、vpath
 清除所有已被設定好了的檔案搜尋目錄。

 vapth 使用方法中的需要包含“%”字元。“%”的意思是匹配零或若干字元,
例如,“%.h”表示所有以“.h”結尾的檔案。指定了要搜尋的檔案集,而
則指定了的檔案集的搜尋的目錄。例如:

vpath %.h ../headers   

 該語句表示,要求 make 在“../headers”目錄下搜尋所有以“.h”結尾的檔案。(如果 某檔案在當前目錄沒有找到的話)可以繼續使用vpath語句,以指定不同搜尋策略。
 

vpath %.c foo:bar
vpath % blish

上面的語句表示 .c 檔案先是在 foo目錄,然後是bar目錄,最後是blish目錄。


  • 偽目標

接觸過的clean便是一個偽目標,make時並不生成clean 這個檔案,它只是一個標籤,偽目標的名字不能和檔名重名,不然便失去了偽目標的意義。
 為了避免和檔案重名的情況,引入了一個特殊的標記 “.PHONY”來明確表示這是一個偽目標。
 .PHONY : clean
 只要有這個宣告,不管是否有clean,只要make clean 才能執行clean 。
 
 偽目標一般沒有依賴的檔案。但是,我們也可以為偽目標指定所依賴的檔案。偽目標同 樣可以作為“預設目標”,只要將其放在第一個。一個示例就是,如果你的 Makefile 需要 一口氣生成若干個可執行檔案,但你只想簡單地敲一個 make 完事,並且,所有的目標檔案
都寫在一個 Makefile 中,那麼你可以使用“偽目標”這個特性:

all : prog1 prog2 prog3   
.PHONY : all   

prog1 : prog1.o utils.o   
cc -o prog1 prog1.o utils.o   

prog2 : prog2.o   
cc -o prog2 prog2.o   

prog3 : prog3.o sort.o utils.o   
cc -o prog3 prog3.o sort.o utils.o   

 我們知道,Makefile 中的第一個目標會被作為其預設目標。我們宣告瞭一個“all”的 偽目標,其依賴於其它三個目標。由於偽目標的特性是,總是被執行的,所以其依賴的那三 個目標就總是不如“all”這個目標新。所以,其它三個目標的規則總是會被決議。也就達 到了我們一口氣生成多個目標的目的。“.PHONY : all”宣告瞭“all”這個目標為“偽目 標”。

 隨便提一句,從上面的例子我們可以看出,目標也可以成為依賴。所以,偽目標同樣也 可成為依賴。看下面的例子:

.PHONY: cleanall cleanobj cleandiff   

cleanall : cleanobj cleandiff   
rm program   

cleanobj :   
rm *.o   

cleandiff :   
rm *.diff   

“make clean”將清除所有要被清除的檔案。“cleanobj”和“cleandiff”這兩個偽 目標有點像“子程式”的意思。我們可以輸入“make cleanall”和“make cleanobj”和“make cleandiff”命令來達到清除不同種類檔案的目的。

相關文章