天天看點

makefile .phony targets

Phony Targets

PHONY 目标并非實際的檔案名:隻是在顯式請求時執行指令的名字。有兩種理由需要使用PHONY 目标:避免和同名檔案沖突,改善性能。

如果編寫一個規則,并不産生目标檔案,則其指令在每次make 該目标時都執行。例如:

  clean:

  rm *.o temp

為"rm"指令并不産生"clean"檔案,則每次執行"make

clean"的時候,該指令都會執行。如果目錄中出現了"clean"檔案,則規則失效了:沒有依賴檔案,檔案"clean"始終是最新的,指令永遠不會

執行;為避免這個問題,可使用".PHONY"指明該目标。如:

  .PHONY : clean

  這樣執行"make clean"會無視"clean"檔案存在與否。

已知phony 目标并非是由其它檔案生成的實際檔案,make 會跳過隐含規則搜尋。這就是聲明phony 目标會改善性能的原因,即使你并不擔心實際檔案存在與否。

  完整的例子如下:

  clean :

phony 目标可以有依賴關系。當一個目錄中有多個程式,将其放在一個makefile 中會更友善。因為預設目标是makefile 中的第一個目标,通常将這個phony 目标叫做"all",其依賴檔案為各個程式:

  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

假設你的一個項目最後需要産生兩個可執行檔案。你的主要目标 是産生兩個可執行檔案,但這兩個檔案是互相獨立的——如果一

個檔案需要重建,并不影響另一個。你可以使用“假象目的”來 達到這種效果。一個假象目的跟一個正常的目的幾乎是一樣的,

隻是這個目的檔案是不存在的。是以, make 總是會假設它需要 被生成,當把它的依賴檔案更新後,就會執行它的規則裡的指令 行。

如果在我們的 makefile 開始處輸入:

all : exec1 exec2

其中 exec1 和 exec2 是我們做為目的的兩個可執行檔案。 make 把這個 'all' 做為它的主要目的,每次執行時都會嘗試把

'all' 更新。但既然這行規則裡沒有哪個指令來作用在一個叫 'all' 的 實際檔案(事實上 all 并不會在磁碟上實際産生),是以這個規

則并不真的改變 'all' 的狀态。可既然這個檔案并不存在,是以 make 會嘗試更新 all 規則,是以就檢查它的依靠 exec1,

exec2 是否需要更新,如果需要,就把它們更新,進而達到我們的目的。

假象目的也可以用來描述一組非預設的動作。例如,你想把所有由 make 産生的檔案删除,你可以在 makefile 裡設立這樣一個規則:

veryclean :

rm *.o

rm myprog

前提是沒有其它的規則依靠這個 'veryclean' 目的,它将永遠 不會被執行。但是,如果你明确的使用指令 'make veryclean' , make 會把這個目的做為它的主要目标,執行那些 rm 指令。

如果你的磁碟上存在一個叫 veryclean 檔案,會發生什麼事?這 時因為在這個規則裡沒有任何依靠檔案,是以這個目的檔案一定是

最新的了(所有的依靠檔案都已經是最新的了),是以既使使用者明 确指令 make 重新産生它,也不會有任何事情發生。解決方法是标

明所有的假象目的(用 .PHONY),這就告訴 make 不用檢查它們 是否存在于磁碟上,也不用查找任何隐含規則,直接假設指定的目

的需要被更新。在 makefile 裡加入下面這行包含上面規則的規則:

.PHONY : veryclean

就可以了。注意,這是一個特殊的 make 規則,make 知道 .PHONY 是一個特殊目的,當然你可以在它的依靠裡加入你想用的任何假象 目的,而 make 知道它們都是假象目的。

繼續閱讀