Makefile學習筆記2

Makefile學習筆記2

Makefile規則

makefile中終極目標只有一個,必須是第一個。其他規則的書寫順序在makefile中沒有意義
多目標中,第一個將會被作爲終極目標。

終極目標是執行make的唯一目的,其所在的規則作爲第一個被執行的規則。而其他的規則時在完成重建“終極目標”的過程中被連帶出來的。所以這些目標所在的規則在Makefile中的順序無關緊要。

依賴的類型

兩種依賴關係:
1. 常規依賴

只要這個依賴有更新,就會更新目標
2. order-only依賴
只在目標不存在的情況下,依賴纔會被更新,否則這個以來的規則不會更新

書寫方法

LIBS=libtest.a
foo: foo.c | $(LIBS)
    $(CC) $(CFLAGS) $< -o $(LIBS)

foo.c就是常規依賴,foo.c比foo新時,就會重新生成foo
libtest.a就是order-only依賴,更新時,foo不會重新生成。

文件名使用通配符

Makefile中表示文件名時可使用通配符。可使用的通配符有“*”,“?”和“[…]”。
可以用在兩個地方:
1. 規則的目標和依賴中
2. 規則的命令中
除了這兩種上下文,其他的場景不能直接使用通配符,要使用函數wildcard來處理

舉例:

clean:
    rm -f *.o

函數wildcard

objects=$(wildcard *.o)

目標搜尋

依賴文件的搜索路徑
環境變量VPATH
關鍵字vpath

僞目標

強制目標(沒有命令或依賴的規則)

強制目標被認爲總是更新過的,把這個目標作爲依賴時,依賴它的目標總是被更新
比如:

clean: force
    rm -f *.o

force:;

因爲force被認爲總是更新過的,所以make會認爲force比clean新,導致clean的命令總是被執行。

空目標文件

僞目標的一個變種。
空目標文件通常是一個空文件,它只用來記錄被更新的時間
如:

print: foo.c bar.c
    lpr -p $?
    touch print

執行make print時,如果print不存在,print會被創建,其次,如果foo.c或bar.c比print新時,命令也會被執行,否則不執行命令。

Makefile的特殊目標

.PHONY:定義僞目標, 僞目標所在的規則定義的命令會被無條件執行
.SUFFIXES:特殊目標“SUFFIXES”的所有依賴指出了一系列在後綴規則中需要檢查的後綴名。

.DEFAULT:這個規則定義的命令,被用在重建哪些沒有具體規則的目標。
.PRECIOUS:目標“.PRECIOUS”的所有依賴文件在make過程中會被特殊處理:當命令在執行過程中被中斷時,make不會刪除它們。而且如果目標的依賴文件是中間過程文件,同樣這些文件不會被刪除。這一點目標“.PRECIOUS”和目標“.SECONDARY”實現的功能相同。
.INTERMEDIATE:目標“.INTERMEDIATE”的依賴文件在make時被作爲中間過程文件對待。沒有任何依賴文件的目標”.INTERMEDIATE”沒有意義。
.SECONDARY:目標“.SECONDARY”的依賴文件被作爲中間過程文件對待。但這些文件不會被自動刪除。沒有熱河依賴文件的目標“.SECONDARY”的含義是:將所有的文件作爲中間過程文件(不會自動刪除任何文件)。
.DELETE_ON_ERROR:如果在Makefile中存在特殊目標“.DELETE_ON_ERROR”,make在執行過程中,如果規則的命令執行錯誤,將刪除一杯修改的目標文件。
.IGNORE:如果給目標“.IGNORE”指定依賴文件,則忽略創建這個文件所執行命令的錯誤。給此目標指定命令時沒有意義的。當此目標沒有依賴文件時,將忽略所喲命令執行的錯誤。
.LOW_RESOLUTION_TIME:目標“.LOW_RESOLUTION_TIME”的依賴文件被make認爲是低分辨率的時間戳文件。
.SILENT: 出現在目標“.SILENT”的依賴列表中的文件,make在創建這些文件時,不打印出重建此文件做執行的命令,沒有依賴文件,表示不打印任何命令。
.EXPORT_ALL_VARIABLES:此目標應該作爲一個簡單的沒有依賴的目標,它的功能含義是將之後所有的變量傳遞給子make進程。
.NOTPARALLEL:Makefile中,如果出現目標“.NOPARALLEL”,則所有命令按照串行方式執行,即使存在make -j參數。

多目標

一個規則中可以有多個目標,規則的命令對所有的目標有效。相當於多個規則,規則的命令對不同的目標執行效果不同,多目標意味所有的目標有相同的依賴。
通常有兩種情況:
* 僅需要一個描述依賴關係的規則,不需要在規則中定義命令。例如:

kbd.o command.o files.o: command.h

多規則目標

Makefile中,一個文件可以作爲多個規則的目標。

靜態模式

規則存在多個目標,並且不同的目標可以根據目標的文件的名字自動構造出依賴文件。
靜態模式的基本語法:

TARGETS ... : TARGET-PATTERN : PREREQ-PATTERNS ...
    COMMANDS
    ...

例如:

objects:=foo.o bar.o

all: $(objects)

$(objects): %.o : %.c
    $(CC) -c $(CFLAGS) $< -o $@

如果目標文件列表中,規則不同,可以使用filter函數進行分類,不同類別的目標,指定不同的規則命令。

靜態模式和隱含規則

雙冒號規則

一個目標可以出現在多個規則中。但是這些規則必須是同一類型的規則,要麼都是普通規則, 要麼都是雙冒號規則。而不允許一個目標同時出現在兩種不同類型的規則中。
雙冒號規則和普通規則的區別:
1. 雙冒號規則中,當依賴文件比目標更新時。規則將會被執行。對於一個沒有依賴而只有命令行的雙冒號規則,當引用此目標時,規則的命令將會被無條件執行。而普通規則,當規則的目標文件存在時,此規則的命令永遠不會被執行(目標文件永遠是最新的)。
2. 當同一個文件作爲多個雙冒號規則的目標時。這些不同的規則會被獨立的處理,而不是像普通規則那樣合併所有的依賴到一個目標文件。這就意味着對這些規則的處理就像多個不同的普通規則一樣。就是說多個雙冒號規則中的每一個的依賴文件被改變之後, make 只執行此規則定義的命令,而其它的以這個文件作爲目標的雙冒號規則將不會被執行。

自動產生依賴

%.d:%.c
    $(CC) -M $(CPPFLAGS) $< > $@.$$$$; \
    sed 's,\($*\).o[:]*,\1.o $@:,g' < $@.$$$$ > $@; \
    rm -f $@.$$$$

使用時如:

sources = foo.c bar.c
include $(sources:.c=.d)  #必須出現在終極目標之後
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章