在前邊的兩個章節中,我們提到了makefile中的目標,並且知道這個目標存在且依賴沒有更新,make就不再編譯程序。
一般在默認的情況下
- make 認爲目標對應着一個文件(可執行程序、so庫等等)
- 比較目標文件和依賴的新舊關係,決定是否執行命令
- make以文件處理作爲第一優先級
clean :
rm *.o hello.out
在上邊的一個簡單的makefile文件中,當我們執行make clean時,就會刪除.o、hello.out文件,因爲clean目標被make認爲是文件,當目錄下有一個文件叫clean時,make clean 下的命令便不會執行。所以我們希望clean 不對應文件,僅僅對應一個類似標籤這樣的東西。
解決方案:引入僞目標
- makefile中的僞目標通過 .PHONY關鍵字聲明
- 僞目標不對應任何實際的文件,其下的命令總是執行
僞目標需要先聲明後使用,聲明語法爲 .PHONY : clean
僞目標本質爲.PHONY目標的依賴
.PHONY : clean #聲明clean爲僞目標
clean :
rm *.o hello.out
此時執行make clean,其他的命令總是被執行,不關注依賴是否有更新
一、僞目標的使用技巧1
我們在編譯程序的時候,希望make包含的功能有刪除現有文件、編譯、重編譯(先刪除後編譯),這時候可以使用僞目標,makefile文件如下
.PHONY clean rebuild all #聲明3個僞目標
rebuild : clean all #僞目標 rebuild 依賴與僞目標 clean 與 all
all : main.o func.o
gcc -o hello.out main.o func.o
main.o : main.c
gcc -o main.o -c main.c
func.o : func.c
gcc -o func.o -c func.c
clean :
rm *.o hello.out
在如上的makefile中,我們定義了三個僞目標 clean、 rebuild、 all,並且將rebuild的僞目標依賴設爲clean、all,所以當執行make rebuild時,就會先執行clean all 僞目標下的命令,這有點類似函數調用。
調用原理:當一個僞目標的依賴包含僞目標時,僞目標所定義的命令總是會被執行
執行make rebuild的結果如下(每次都是強制重編)
/home/delphi/myshare/makefile>make rebuild
rm *.o hello.out
gcc -o main.o -c main.c
gcc -o func.o -c func.c
gcc -o hello.out main.o func.o
/home/delphi/myshare/makefile>
二、僞目標的使用技巧2
繞開.PHONY關鍵字定位僞目標
在開始這個技巧之前,首先來看一個原理:
如果一個規則沒有命令或者依賴,並且其目標不是一個存在的文件名,那麼在執行此規則時,目標總是會被認爲最新的
FORCE:
如上的規則只有一個目標FORCE,沒有依賴、沒有命令,只要makefile目錄下沒有文件名爲FORCE的文件,那麼make FORCE時,命令總是被執行(當然這裏的命令爲空),有了以上理解,來看下如下的makefile
clean : FORCE
rm -f *.o hello.out
FORCE:
clean依賴的目標FORCE既沒有依賴也沒有命令,那麼FORCE這個目標總是被認爲是最新的,所以每次執行make clean時,rm *.o hello.out 命令總是被執行,不管目錄下有沒有clean這個文件存在(因爲其依賴FORCE總是被認爲最新的),
/home/delphi/myshare/makefile>make clean
rm -f *.o hello.out
/home/delphi/myshare/makefile>make clean
rm -f *.o hello.out
/home/delphi/myshare/makefile>
小結:
- 默認情況下,make認爲目標對應着一個文件
- .PHONY用於聲明一個僞目標,僞目標不對應實際的文件
- 僞目標的本質是make中特殊目標.PHONY的依賴
- 使用僞目標可以模擬"函數調用"
以上內容參考《狄泰軟件學院》操作系統篇之 - makefile專題