模式規則
模式規則類似於普通規則。只是在模式規則中,目標名中需要包含有模式字符“%”(一個),包含有模式字符“%”的目標被用來匹配一個文件名,“%”可以匹配任何非空字符串。規則的依賴文件中同樣可以使用“%”,依賴文件中模式字符“%”的取值情況由目標中的“%”來決定。例如:對於模式規則“%.o : %.c”,它表示的含義是:所有的.o文件依賴於對應的.c文件。我們可以使用模式規則來定義隱含規則。
要注意的是:模式字符“%”的匹配和替換發生在規則中所有變量和函數引用展開之后,變量和函數的展開一般發生在make讀取Makefile時(變量和函數的展開可參考第五 章 使用變量 和 第七章 make的函數),而模式規則中的“%”的匹配和替換則發生在make執行時。
模式規則介紹
在模式規則中,目標文件是一個帶有模式字符“%”的文件,使用模式來匹配目標文件。文件名中的模式字符“%”可以匹配任何非空字符串,除模式字符以外的部分要求一致。例如:“%.c”匹配所有以“.c”結尾的文件(匹配的文件名長度最少為3個字母),“s%.c”匹配所有第一個字母為“s”,而且必須以“.c”結尾的文件,文件名長度最小為5個字符(模式字符“%”至少匹配一個字符)。在目標文件名中“%”匹配的部分稱為“莖”(前面已經提到過,參考4.12 靜態模式一節)。使用模式規則時,目標文件匹配之后得到“莖”,依賴根據“莖”產生對應的依賴文件,這個依賴文件必須是存在的或者可被創建的。
因此,一個模式規則的格式為:
%.o : %.c ; COMMAND...
這個模式規則指定了如何由文件“N.c”來創建文件“N.o”,文件“N.c”應該是已存在的或者可被創建的。
模式規則中依賴文件也可以不包含模式字符“%”。當依賴文件名中不包含模式字符“%”時,其含義是所有符合目標模式的目標文件都依賴於一個指定的文件(例如:%.o : debug.h,表示所有的.o文件都依賴於頭文件“debug.h”)。這樣的模式規則在很多場合是非常有用的。
同 樣一個模式規則可以存在多個目標。多目標的模式規則和普通多目標規則有些不同,普通多目標規則的處理是將每一個目標作為一個獨立的規則來處理,所以多個目 標就就對應多個獨立的規則(這些規則各自有自己的命令行,各個規則的命令行可能相同)。但對於多目標模式規則來說,所有規則的目標共同擁有依賴文件和規則 的命令行,當文件符合多個目標模式中的任何一個時,規則定義的命令就有可能將會執行;因為多個目標共同擁有規則的命令行,因此一次命令執行之后,規則不會 再去檢查是否需要重建符合其它模式的目標。看一個例子:
#sample Makefile
Objects = foo.o bar.o
CFLAGS := -Wall
%x : CFLAGS += -g
%.o : CFLAGS += -O2
%.o %.x : %.c
$(CC) $(CFLAGS) $< -o $@
當在命令行中執行“make foo.o foo.x”時,會看到只有一個文件“foo.o”被創建了,同時make會提示“foo.x”文件是最新的(其實“foo.x”並沒有被創建)。此過程表明了多目標的模式規則在make處理時是被作為一個整體來處理的。這是多目標模式規則和多目標的普通規則的區別之處。大家不妨將上邊的例子改為普通多目標規則試試看將會得到什么樣的結果。
最后需要說明的是:
1. 模式規則在Makefile中的順序需要注意,當一個目標文件同時符合多個目標模式時,make將會把第一個目標匹配的模式規則作為重建它的規則。
2. Makefile中明確指定的模式規則會覆蓋隱含模式規則。就是說如果在Makefile中出現了一個對目標文件合適可用的模式規則,那么make就不會再為這個目標文件尋找其它隱含規則,而直接使用在Makefile中出現的這個規則。在使用時,明確規則永遠優先於隱含規則。
3. 另外,依賴文件存在或者被提及的規則,優先於那些需要使用隱含規則來創建其依賴文件的規則。
模式規則示例
本小節來看一些使用模式規則的例子,這些模式規則在GNU make中已經被預定義。首先看編譯.c文件到.o文件的隱含模式規則:
%.o : %.c
$(CC) -c $(CFLAGS) $(CPPFLAGS) $< -o $@
此規則描述了一個.o文件如何由對應的.c文件創建。規則的命令行中使用了自動化變量“$<”和“$@”,其中自動化變量“$<”代表規則的依賴,“$@”代表規則的目標。此規則在執行時,命令行中的自動化變量將根據實際的目標和依賴文件取對應值。關於自動化變量可參考10.5.3 自動化變量一節
make中第二個內嵌模式規則是:
% :: RCS/%,v
$(CO) $(COFLAGS) $<
這個規則的含義是:任何一個文件“X”都可以由目錄“RCS”下的相應文件“x.v”來生成。規則的目標為“%”,它匹配任何文件名,因此只要存在相對應的依賴文件(N.v),目標(N)都可被創建。雙冒號表示該規則是最終規則,意味着規則的依賴文件不是中間過程文件。參考10.6 萬用規則一節
另外,一個具有多目標的隱含規則是:
%.tab.c %.tab.h: %.y
bison -d $<
它是一個多目標模式規則,關於多目標的特征可參考 10.5.1 模式規則介紹一小節最后一個例子。