makefile中PHONY的重要性

2021-09-06 12:43:45 字數 3570 閱讀 7132

偽目標是這樣乙個目標:它不代表乙個真正的檔名,在執行make時可以指定這個目標來執行所在規則定義的命令,有時也可以將乙個偽目標稱為標籤。偽目標通過   phony來指明。

phony定義偽目標的命令一定會被執行,下面嘗試分析這種優點的妙處。

1、如果我們指定的目標不是建立目標檔案,而是使用makefile執行一些特定的命令,例如:

clean:

rm *.o temp

我們希望,只要輸入」make clean「後,」rm *.o temp「命令就會執行。但是,當當前目錄中存在乙個和指定目標重名的檔案時,例如clean檔案,結果就不是我們想要的了。輸入」make clean「後,「rm *.o temp」 命令一定不會被執行。

解決的辦法是,將目標clean定義成偽目標就成了。無論當前目錄下是否存在「clean」這個檔案,輸入「make clean」後,「rm *.o temp」命令都會被執行。

注意:這種做法的帶來的好處還不止此,它同時提高了make的執行效率,因為將clean定義成偽目標後,make的執行程式不會試圖尋找clean的隱含規則。

2、phony可以確保原始檔(*.c *.h)修改後,對應的目標檔案會被重建。倘若缺少了phony,可以看到情況會很糟。

現在做乙個實驗,實驗的目錄是/work,在這個目錄中,包含了四個目錄test、add、sub、include 和乙個頂層目錄makefile檔案。test、add、sub三個目錄分別包含了三個源程式test.c、add.c、sub.c和三個子目錄makefile,目錄include的是標頭檔案heads.h的目錄,分別展開四個目錄的內容如下。

test目錄
test.c

#include #include

"../include/heads.h

"int

main()

makefile

test.o:test.c ../include/heads.h

gcc -c -o $@ $<

.phony: clean

clean:

rm -f *.o

add目錄

add.c

#include

"../include/heads.h

"int add(int a,int

b)makefile

add.o :add.c ../include/heads.h

gcc -c -o $@ $<

.phony: clean

clean:

rm -f *.o

sub目錄

sub.c

#include

"../include/heads.h

"int sub(int a,int

b)makefile

sub.o:sub.c ../include/heads.h

gcc -c -o $@ $<

.phony: clean

clean:

rm -f *.o

inlcude目錄

heads.h

#ifndef _head_h_

#define _head_h_

extern

int add(int,int

);extern

int sub(int,int

);#endif

頂層makefile檔案

objs = ./add/add.o ./sub/sub.o ./test/test.o

program: $(objs)

gcc ./test/test.o ./add/add.o ./sub/sub.o -o program

$(objs):

make -c $(dir $@)

.phony: clean

clean:

make -c ./add clean

make -c ./sub clean

make -c ./test clean

rm -f program

編譯除錯:當在/work目錄中,執行make後,編譯出了program應用程式。修改了任意乙個原始檔(test.c、sub.c、add.c、heads.h)例如test.c,重新在/work目錄中執行make,發現一直提示「make: `program' is up to date.」 ,而不能重建test.o,更不用說重建program。

修改頂層makefile檔案,新增紅色的一行

objs = ./add/add.o ./sub/sub.o ./test/test.o

program: $(objs)

gcc ./test/test.o ./add/add.o ./sub/sub.o -o program

.phony : $(objs)

$(objs):

make -c $(dir $@)

.phony: clean

clean:

make -c ./add clean

make -c ./sub clean

make -c ./test clean

rm -f program

加上偽目標修改後,問題就會解決。修改了任意乙個原始檔,執行make對應的目標檔案就會重建,最後重建program。即使不修改原始檔,執行make也會進入源檔案目錄中執行子make,但不會更新目標檔案,最後還要重建program。

原因分析:由於(*.c *.h)- - > (*.o)- - > (program),修改前的頂層目標(program)依賴於(*.o)。執行make時,檢查 (program)的依賴(*.o)是否比(program)新,而不會檢查(*.h *.c)是否比(program)新,(*.h *.c)不是(program)的依賴。顯然,(*.o)沒有program新,所以不用重建。

注意修改後的makefile,把./add/add.o ./sub/sub.o ./test/test.o當做三個偽目標,所以不會再檢查 (program)的依賴(*.o)是否比(program)新。而原來的makefile中把./add/add.o ./sub/sub.o ./test/test.o當做三個依賴檔案。可以說加上「phony」後,make程式對./add/add.o ./sub/sub.o ./test/test.o的看法已經完全不一樣了。

修改後的makefile,強制執行./add/add.o ./sub/sub.o ./test/test.o這三個偽目標的命令,即進入相應的子目錄執行make,從而呼叫相應的子目錄makefile。由於子目錄中的makefile目標是(*.o),目標的依賴是(*.c heads.h),會檢查(*.c heads.h)是否比(*.o)新,從而有可能重建(*.o)。而在跳回到頂層makefile後,還要執行「 gcc ./test/test.o ./add/add.o ./sub/sub.o -o program」。

總結:phony偽目標可以解決原始檔不是最終目標直接依賴(實際上可以認為是間接依賴)帶來的不能自動檢查更新規則。

MAKEFILE中 PHONY的作用

本文 main1.c include intmain void main2.c include intmain void 分析 這裡需要生成兩個可執行檔案main1和main2 兩個目標 由於makefile只能有乙個目標,所以可以構造乙個沒有規則的終極目標all,並以這兩個可執行檔案作為依賴。如下...

Makefile中 PHONY的作用

拿clean舉例,如果make完成後,自己另外定義乙個名叫clean的檔案,再執行make clean時,將不會執行rm命令。為了避免出現這個問題,需要.phony clean 圖示 1 不新增.phony clean 在makefile所在的目錄下touch乙個clean檔案 執行make 執行m...

makefile中的all和 PHONY的作用

請編寫乙個makefile同時編譯 鏈結下面兩個程式 main1.c include int main void main2.c include int main void 分析 這裡需要生成兩個可執行檔案main1和main2 兩個目標 由於makefile只能有乙個目標,所以可以構造乙個沒有規則...