2016年3月2日 星期三

Makefile .Phony

.Phony 可以參考這邊的敘述
偽目標
最早先的一個例子中,我們提到過一個“clean”的目標,這是一個“偽目標”,

clean:
rm *.o temp
正像我們前面例子中的“clean”一樣,既然我們生成了許多文件編譯文件,我們也應該提供一個清除它們的“目標”以備完整地重編譯而用。 (以“make clean”來使用該目標)

因為,我們並不生成“clean”這個文件。“偽目標”並不是一個文件,只是一個標籤,由於“偽目標”不是文件,所以make無法生成它的依賴關係和決定它是否要執行。我們只有通過顯式地指明這個“目標”才能讓其生效。當然,“偽目標”的取名不能和文件名重名,不然其就失去了“偽目標”的意義了。

當然,為了避免和文件重名的這種情況,我們可以使用一個特殊的標記“.PHONY”來顯式地指明一個目標是“偽目標”,向make說明,不管是否有這個文件,這個目標就是“偽目標”。

.PHONY : clean
只要有這個聲明,不管是否有“clean”文件,要運行“clean”這個目標,只有“make clean”這樣。於是整個過程可以這樣寫:

.PHONY : clean
clean :
rm *.o temp
偽目標一般沒有依賴的文件。但是,我們也可以為偽目標指定所依賴的文件。偽目標同樣可以作為“默認目標”,只要將其放在第一個。一個示例就是,如果你的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”又是一個偽目標,偽目標只是一個標籤不會生成文件,所以不會有“all”文件產生。於是,其它三個目標的規則總是會被決議。也就達到了我們一口氣生成多個目標的目的。“.PHONY : all”聲明了“all”這個目標為“偽目標”。(注:這裏的顯式 “.PHONY : all" 不寫的話一般情況也可以正確的執行,這樣 make 可通過隱式規則推導出, “all" 是一個偽目標,執行 make 不會生成 ”all" 文件,而執行後面的多個目標。建議:顯式寫出是一個好習慣。)

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

.PHONY : cleanall cleanobj cleandiff

cleanall : cleanobj cleandiff
rm program

cleanobj :
rm *.o

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

沒有留言:

張貼留言