1 GNU make介紹
make 在執(zhí)行時(shí)悦冀,需要一個(gè)命名為 Makefile 的文件趋翻。這個(gè)文件告訴 make 以何種方式編譯源代碼和鏈接程序。典型地盒蟆,可執(zhí)行文件可由一些.o 文件按照一定的順序生成或者更新踏烙。如果在你的工程中已經(jīng)存在一個(gè)或者多個(gè)正確的 Makefile。當(dāng)對(duì)工程中的若干源文件修改以后历等,需要根據(jù)修改來(lái)更新可執(zhí)行文件或者庫(kù)文件讨惩,正如前面提到的你只需要在 shell 下執(zhí)行“ make”。 make 會(huì)自動(dòng)根據(jù)修改情況完成源文件的對(duì)應(yīng).o 文件的更新寒屯、庫(kù)文件的更新荐捻、最終的可執(zhí)行程序的更新。make 通過(guò)比較對(duì)應(yīng)文件(規(guī)則的目標(biāo)和依賴浩螺,)的最后修改時(shí)間,來(lái)決定哪些文件需要更新仍侥、那些文件不需要更新要出。對(duì)需要更新的文件 make 就執(zhí)行數(shù)據(jù)庫(kù)中所記錄的相應(yīng)命令(在 make 讀取 Makefile 以后會(huì)建立一個(gè)編譯過(guò)程的描述數(shù)據(jù)庫(kù)。此數(shù)據(jù)庫(kù)中記錄了所有各個(gè)文件之間的相互關(guān)系农渊,以及它們的關(guān)系描述)來(lái)重建它患蹂,對(duì)于不需要重建的文件 make 什么也不做或颊。
2 Makefile規(guī)則介紹
簡(jiǎn)單的Makefile描述規(guī)則組成:
TARGET... : PREREQUISITES...
COMMAND
...
...
target:規(guī)則的目標(biāo)。通常是最后需要生成的文件名或者為了實(shí)現(xiàn)這個(gè)目的而必需的中間過(guò)程文件名传于〈烟簦可以是.o文件、也可以是最后的可執(zhí)行程序的文件名等沼溜。另外平挑,目標(biāo)也可以是一個(gè)make執(zhí)行的動(dòng)作的名稱,如目標(biāo)“ clean”系草,我們稱這樣的目標(biāo)是“偽目標(biāo)”通熄。
prerequisites:規(guī)則的依賴。生成規(guī)則目標(biāo)所需要的文件名列表找都。通常一個(gè)目標(biāo)依賴于一個(gè)或者多個(gè)文件唇辨。
command:規(guī)則的命令行。是規(guī)則所要執(zhí)行的動(dòng)作(任意的 shell 命令或者是可在shell 下執(zhí)行的程序)能耻。它限定了 make 執(zhí)行這條規(guī)則時(shí)所需要的動(dòng)作赏枚。
一個(gè)規(guī)則可以有多個(gè)命令行,每一條命令占一行晓猛。 注意: 每一個(gè)命令行必須以[Tab]字符開始饿幅,[Tab] 字符告訴 make 此行是一個(gè)命令行。 make 按照命令完成相應(yīng)的動(dòng)作鞍帝。這也是書寫 Makefile 中容易產(chǎn)生诫睬,而且比較隱蔽的錯(cuò)誤。
main : main.o test1.o test2.o
gcc -o main main.o test1.o test2.o
main.o : main.c test1.h test2.h
gcc -o main.o -c main.c
test1.o : test1.c test1.h
gcc -o test1.o -c test1.c
test2.o : test2.c test2.h
gcc -o test2.o -c test2.c
在上述Makefile中,我們的目標(biāo)(target)就是可執(zhí)行文件 "main"和那些.o文件(main.o,test1.o,test2.o);依賴(prerequisites)就是冒號(hào)后面的那些.c文件和.h文件帕涌。所有的.o文件既是依賴又是目標(biāo)摄凡。命令包括 "gcc -o main.o -c main.c"......
3 Makefile語(yǔ)法
3.1 通配符
Maekfile 中表示文件名時(shí)可使用通配符◎韭可使用的通配符有:" * ","?"和 "[...]"
Makefile 中通配符可以出現(xiàn)在以下兩種場(chǎng)合:
- 可以用在規(guī)則的目標(biāo)亲澡、依賴中, make 在讀取 Makefile 時(shí)會(huì)自動(dòng)對(duì)其進(jìn)行匹配處理(通配符展開);
- 可出現(xiàn)在規(guī)則的命令中纫版,通配符的通配處理是在 shell 在執(zhí)行此命令時(shí)完成的床绪。除這兩種情況之外的其它上下文中,不能直接使用通配符其弊。而是需要通過(guò)函數(shù)"wildcard"來(lái)實(shí)現(xiàn)癞己。
3.2 偽目標(biāo)
偽目標(biāo)是這樣一個(gè)目標(biāo):它不代表一個(gè)真正的文件名,在執(zhí)行 make 時(shí)可以指定這個(gè)目標(biāo)來(lái)執(zhí)行其所在規(guī)則定義的命令梭伐,有時(shí)也可以將一個(gè)偽目標(biāo)稱為標(biāo)簽痹雅。使用偽目標(biāo)有兩點(diǎn)原因,避免在我們的 Makefile 中定義的只執(zhí)行命令的目標(biāo)(此目標(biāo)的目的為了執(zhí)行執(zhí)行一些列命令,而不需要?jiǎng)?chuàng)建這個(gè)目標(biāo))和工作目錄下的實(shí)際文件出現(xiàn)名字沖突糊识。比如:我們書寫這樣一個(gè)規(guī)則,規(guī)則所定義的命令不是去創(chuàng)建目標(biāo)文件,而是通過(guò)make命令行明確指定它來(lái)執(zhí)行一些特定的命令.常見的有clean目標(biāo)
clean:
rm *.o main
規(guī)則中 "rm"不是創(chuàng)建文件 "clean"命令,而是刪除當(dāng)前目錄下的所有.o文件和main文件绩社。當(dāng)工作目錄下不存在 "clean"這個(gè)文件時(shí),我們輸入 "make clean"則 "rm *.o main"總會(huì)被執(zhí)行摔蓝。但是如果在當(dāng)前工作目錄下存在文件 "clean",情況就不一樣了,同樣輸入 "make clean",由于這個(gè)規(guī)則沒(méi)有任何依賴文件,所以目標(biāo)被認(rèn)為是最新的而不去執(zhí)行規(guī)則所定義的命令,因此命令 "rm"將不會(huì)被執(zhí)行。為了解決這個(gè)問(wèn)題,我們需要將目標(biāo)"clean"聲明為偽目標(biāo),如下:
.PHONY : clean
clean:
rm *.o main
這樣目標(biāo) "clean"就被聲明為一個(gè)偽目標(biāo)了,無(wú)論在當(dāng)前目錄下是否存在 "clean"這個(gè)文件愉耙。輸入 "make clean"之后,"rm"命令都會(huì)被執(zhí)行.
3.3 變量
當(dāng)我們定義了一個(gè)變量之后贮尉,就可以在 Makefile 的很多地方使用這個(gè)變量。變量的引用方式是:
“$(VARIABLE_NAME)”或者“ ${ VARIABLE_NAME }”來(lái)引用一個(gè)變量的定義朴沿。例如:“ $(foo) ”或者“ ${foo}”就是取變量“ foo”的值猜谚。
在 GNU make 中,變量的定義有兩種方式(或者稱為風(fēng)格).我們把使用這兩種方式定義的變量可以看作變量的兩種不同風(fēng)格悯仙。變量的這兩種不同的風(fēng)格的區(qū)別在于:1.定義方式;2. 展開時(shí)機(jī)龄毡。下邊我們分別對(duì)這兩種不同的風(fēng)格進(jìn)行詳細(xì)地討論。
3.3.1 遞歸展開式變量
遞歸展開式變量的定義是通過(guò)"="或者使用指示符 "define"定義的锡垄。這種變量的引用,在引用的地方是嚴(yán)格的文本替換過(guò)程,此變量的字符串原模原樣的出現(xiàn)在引用它的地方.變量在定義時(shí),變量值中對(duì)其它變量的引用不會(huì)被替換展開;而是變量在引用它的地方替換展開的同時(shí),它所引用的其它變量才會(huì)被一同替換展開沦零。
foo = $(bar)
bar = $(ugh)
ugh = hello
all:
@echo $(foo)
執(zhí)行 "make"將會(huì)打印出 "hello".整個(gè)變量的替換過(guò)程是在執(zhí)行 "@echo $(foo)"時(shí)完成的.
這種遞歸展開式變量?jī)?yōu)點(diǎn)是:該變量在定義時(shí),可以引用其它的之前沒(méi)有定義的變量(可能在后續(xù)部分定義,或者是通過(guò)make的命令行選項(xiàng)傳遞的變量)。缺點(diǎn)是使用該變量,可能會(huì)導(dǎo)致make陷入到無(wú)限的變量展開過(guò)程中,最終使make執(zhí)行失敗货岭。
3.3.2 直接展開式變量
直接展開式變量的定義是通過(guò)":="定義的路操。在使用 ":="定義變量時(shí),變量值中對(duì)其它變量或者函數(shù)得引用在定義變量時(shí)被展開(對(duì)變量進(jìn)行替換).所以變量被定義后就是一個(gè)實(shí)際需要的字符串。和遞歸展開式變量不同,此變量在定義時(shí)就完成了對(duì)所引用變量和函數(shù)的展開,因此不能實(shí)現(xiàn)對(duì)其后定義變量的引用千贯。
3.3.3 "?="操作符
GNU make 中屯仗,還有一個(gè)被稱為條件賦值的賦值操作符“ ?=”.被稱為條件賦值是因?yàn)?只有此變量在之前沒(méi)有賦值的情況下才會(huì)對(duì)這個(gè)變量進(jìn)行賦值。例如:
FOO ?= bar
等價(jià)于:
ifeq ($(origin FOO), undefined)
FOO = bar
endif
3.3.4 追加變量值
通常,一個(gè)通用變量在定義之后的其它地方,可以對(duì)其值進(jìn)行追加.在Makefile中使用 "+="(追加方式)來(lái)實(shí)現(xiàn)對(duì)一個(gè)變量的追加操作.
objects = main.o foo.o bar.o utils.o
objects += another.o
上邊的兩個(gè)操作之后變量"objects"的值就為:"main.o foo.o bar.o utils.o another.o".
注:如果被追加值的變量之前沒(méi)有定義,那么,"+="會(huì)自動(dòng)變成"="搔谴,此變量就被定義為一個(gè)遞歸展開式的變量魁袜。如果之前存在這個(gè)變量定義,那么“ +=”就繼承之前定義時(shí)的變量風(fēng)格.
4 為規(guī)則書寫命令
4.1 命令回顯
通常,make 在執(zhí)行命令行之前會(huì)把要執(zhí)行的命令行輸出到標(biāo)準(zhǔn)輸出設(shè)備敦第。我們稱之為“回顯”峰弹,就好像我們?cè)?shell 環(huán)境下輸入命令執(zhí)行時(shí)一樣。例如:
clean:
rm *.o main
執(zhí)行make clean會(huì)顯示"rm .o main" 該條打印信息,同時(shí)刪除 "所有的.o文件"和main執(zhí)行文件.
但是芜果,如果規(guī)則的命令行以字符"@"開始,則 make在執(zhí)行這個(gè)命令時(shí)就不會(huì)回顯這個(gè)將要被執(zhí)行的命令鞠呈。例如:
clean:
@rm *.o main
執(zhí)行make clean則是直接刪除 "所有的.o文件"和main執(zhí)行文件,不會(huì)有其它的打印信息.
如果想得到更多的輸出信息,典型的用法是使用 "echo"命令,例如:
clean:
echo rm *.o main
執(zhí)行make clean會(huì)顯示命令同時(shí)會(huì)顯示刪除了哪些文件,比如筆者的輸出信息是 "echo rm .o main \n rm main.o test1.o test2.o main","\n"前面是命令,后面是刪除的文件名.
如果不想顯示命令,只顯示刪除的文件名,哪么命令配合@使用即可,比如:
clean:
@echo rm *.o main
執(zhí)行make clean會(huì)顯示刪除了哪些文件,比如筆者的輸出信息是 "rm main.o test1.o test2.o main",這樣就只顯示了刪除的文件名.
4.2 命令的執(zhí)行
規(guī)則中右钾,當(dāng)目標(biāo)需要被重建時(shí)蚁吝。此規(guī)則所定義的命令將會(huì)被執(zhí)行,如果是多行命令舀射,那么每一行命令將在一個(gè)獨(dú)立的子 shell 進(jìn)程中被執(zhí)行(就是說(shuō)窘茁,每一行命令的執(zhí)行是在一個(gè)獨(dú)立的 shell 進(jìn)城中完成)。
因此脆烟,多行命令之間的執(zhí)行是相互獨(dú)立的山林,相互之間不存在依賴(多條命令行的執(zhí)行為多個(gè)相互獨(dú)立的進(jìn)程)。
在 Makefile 中書寫在同一行中的多個(gè)命令屬于一個(gè)完整的 shell 命令行浩淘,書寫在獨(dú)立行的一條命令是一個(gè)獨(dú)立的 shell 命令行捌朴。因此:在一個(gè)規(guī)則的命令中,命令行“ cd”改變目錄不會(huì)對(duì)其后的命令的執(zhí)行產(chǎn)生影響张抄。就是說(shuō)其后的命令執(zhí)行的工作目錄不會(huì)是之前使用“ cd”進(jìn)入的那個(gè)目錄砂蔽。如果要實(shí)現(xiàn)這個(gè)目的, 就不能把“ cd”和其后的命令放在兩行來(lái)書寫署惯。而應(yīng)該把這兩條命令寫在一行上左驾,用分號(hào)分隔。這樣它們才是一個(gè)完整的 shell 命令行极谊。如:
foo : bar/lose
cd bar; gobble lose > ../foo
如果希望把一個(gè)完整的 shell 命令行書寫在多行上诡右,需要使用反斜杠( \)來(lái)對(duì)處于多行的命令進(jìn)行連接,表示他們是一個(gè)完整的 shell 命令行轻猖。例如上例我們以也可以這樣書寫:
foo : bar/lose
cd bar; \
gobble lose > ../foo
5 Makefile函數(shù)
5.1 $(patsubst PATTERN,REPLACEMENT,TEXT)
函數(shù)名稱:模式替換函數(shù)— patsubst帆吻。
函數(shù)功能:搜索“ TEXT”中以空格分開的單詞,將否符合模式“ PTATTERN”替換為“ REPLACEMENT”咙边。參數(shù)“PATTERN”中可以使用模式通配符“ %”來(lái)代表一個(gè)單詞中的若干字符猜煮。如果參數(shù) “REPLACEMENT”中也包含一個(gè)“ %”,那么
“ REPLACEMENT”中的“ %”將是“ TATTERN”中的那個(gè)“ %”所代表的字符串败许。在“ TATTERN”和“ REPLACEMENT”中王带,只有第一個(gè)“ %”被作為模式字符來(lái)處理,之后出現(xiàn)的不再作模式字符(作為一個(gè)字符)市殷。
返回值:替換后的新字符串愕撰。
函數(shù)說(shuō)明:參數(shù)“ TEXT”單詞之間的多個(gè)空格在處理時(shí)被合并為一個(gè)空格,并忽略前導(dǎo)和結(jié)尾空格醋寝。
$(patsubst %.c,%.o,x.c.c bar.c)
把字串“ x.c.c bar.c”中以.c 結(jié)尾的單詞替換成以.o 結(jié)尾的字符搞挣。函數(shù)的返回結(jié)果是“ x.c.o bar.o”。
5.2 $(filter PATTERN…,TEXT)
函數(shù)名稱:過(guò)濾函數(shù)-filter
函數(shù)功能:過(guò)濾掉字串“ TEXT”中所有不符合模式“ PATTERN”的單詞甥桂,保留所有符合此模式的單詞柿究。可以使用多個(gè)模式黄选。模式中一般需要包含模式字符“ %”蝇摸。存在多個(gè)模式時(shí),模式表達(dá)式之間使用空格分割办陷。
返回值:空格分割的“ TEXT”字串中所有符合模式“ PATTERN”的字串貌夕。
函數(shù)說(shuō)明:“ filter”函數(shù)可以用來(lái)去除一個(gè)變量中的某些字符串,下邊的例子中就是用到了此函數(shù)民镜。
在參數(shù)中如果需要將第一個(gè)出現(xiàn)的“ %”作為字符本身而不作為模式字符時(shí)啡专,可使用反斜杠“ \”進(jìn)行轉(zhuǎn)義處理。
sources := foo.c bar.c baz.s ugh.h
foo: $(sources)
cc $(filter %.c %.s,$(sources)) -o foo
使用“ $(filter %.c %.s,$(sources))”的返回值給 cc 來(lái)編譯生成目標(biāo)“ foo”制圈,函數(shù)返回值為“ foo.c bar.c baz.s”们童。
5.3 $(filter-out PATTERN...,TEXT)
函數(shù)名稱:反過(guò)濾函數(shù)— filter-out磷籍。
函數(shù)功能:和“ filter”函數(shù)實(shí)現(xiàn)的功能相反菩咨。過(guò)濾掉字串“ TEXT”中所有符合模式“ PATTERN”的單詞,保留所有不符合此模式的單詞⊥蛩祝可以有多個(gè)模式满力。存在多個(gè)模式時(shí)采章,模式表達(dá)式之間使用空格分割惧笛。
返回值:空格分割的“ TEXT”字串中所有不符合模式“ PATTERN”的字串。
函數(shù)說(shuō)明:“ filter-out”函數(shù)也可以用來(lái)去除一個(gè)變量中的某些字符串甘磨,(實(shí)現(xiàn)和“ filter”函數(shù)相反)橡羞。
objects=main1.o foo.o main2.o bar.o
mains=main1.o main2.o
$(filter-out $(mains),$(objects))
實(shí)現(xiàn)了去除變量“ objects”中“ mains”定義的字串(文件名)功能。它的返回值為“ foo.o bar.o”济舆。
5.4 $(wildcard PATTERN)
函數(shù)名稱:獲取匹配模式文件名函數(shù)— wildcard
函數(shù)功能:列出當(dāng)前目錄下所有符合模式“ PATTERN”格式的文件名卿泽。
返回值:空格分割的、存在當(dāng)前目錄下的所有符合模式“ PATTERN”的文件名滋觉。
函數(shù)說(shuō)明:“ PATTERN”使用shell可識(shí)別的通配符又厉,包括“ ?”(單字符)、“ *”(多字符)等椎瘟。
$(wildcard *.c)
返回值為當(dāng)前目錄下所有.c 源文件列表覆致。
5.5 $(foreach VAR,LIST,TEXT)
函數(shù)功能: 這個(gè)函數(shù)的工作過(guò)程是這樣的:如果需要(存在變量或者函數(shù)的引用),首先展開變量“ VAR”和“ LIST”的引用肺蔚;而表達(dá)式“ TEXT”中的變量引用不展開煌妈。執(zhí)行時(shí)把“ LIST”中使用空格分割的單詞依次取出賦值給變量“ VAR”,然后執(zhí)行“ TEXT”表達(dá)式宣羊。重復(fù)直到“ LIST”的最后一個(gè)單詞(為空時(shí)結(jié)束)璧诵。“ TEXT”中的變量或者函數(shù)引用在執(zhí)行時(shí)才被展開仇冯,因此如果在“ TEXT”中存在對(duì)“ VAR”的引用之宿,那么“VAR”的值在每一次展開式將會(huì)到的不同的值。
返回值:空格分割的多次表達(dá)式“ TEXT”的計(jì)算的結(jié)果苛坚。
函數(shù)說(shuō)明:函數(shù)“ foreach”不同于其它函數(shù)比被。它是一個(gè)循環(huán)函數(shù)。類似于 Linux 的 shell 中的for 語(yǔ)句泼舱。
我們來(lái)看一個(gè)例子等缀,定義變量“ files”,它的值為四個(gè)目錄(變量“ dirs”代表的 a娇昙、b尺迂、 c、 d 四個(gè)目錄)下的文件列表:
dirs := a b c d
files := $(foreach dir,$(dirs),$(wildcard $(dir)/*))
例子中,“ TEXT”的表達(dá)式為“ $(wildcard $(dir)/*)”噪裕。表達(dá)式第一次執(zhí)行時(shí)將展開為“ $(wildcard a/)”蹲盘;第二次執(zhí)行時(shí)將展開為 “ $(wildcard b/)”;第三次展開為 “ $(wildcard c/)”….以此類推膳音。所以此函數(shù)所實(shí)現(xiàn)的功能就和一下語(yǔ)句等價(jià):
files := $(wildcard a/* b/* c/* d/*)
當(dāng)函數(shù)的“ TEXT”表達(dá)式過(guò)于復(fù)雜時(shí)辜限,我們可以通過(guò)定義一個(gè)中間變量,此變量代表表達(dá)式的一部分严蓖。并在函數(shù)的“ TEXT”中引用這個(gè)變量。上邊的例子也可以這樣來(lái)實(shí)現(xiàn):
find_files = $(wildcard $(dir)/*)
dirs := a b c d
files := $(foreach dir,$(dirs),$(find_files))
在這里我們定義了一個(gè)變量(也可以稱之為表達(dá)式)氧急,需要注意颗胡,在這里定義的是“遞歸展開”時(shí)的變量“ find_files”。保證了定義時(shí)變量值中的引用不展開吩坝,而是在表達(dá)式被函數(shù)處理時(shí)才展開(如果這里使用直接展開式的定義將是無(wú)效的表達(dá)式)毒姨。
6 隱含規(guī)則
6.1 模式規(guī)則
模式規(guī)則類似于普通規(guī)則。只是在模式規(guī)則中钉寝,目標(biāo)名中需要包含有模式字符“ %”(一個(gè))弧呐,包含有模式字符“ %”的目標(biāo)被用來(lái)匹配一個(gè)文件名,“ %”可以匹配任何非空字符串嵌纲。規(guī)則的依賴文件中同樣可以使用“ %”俘枫,依賴文件中模式字符“ %”的取值情況由目標(biāo)中的“ %”來(lái)決定。例如:對(duì)于模式規(guī)則“ %.o : %.c”逮走,它表示的含義是:所有的.o文件依賴于對(duì)應(yīng)的.c文件鸠蚪。
要注意的是:模式字符“ %”的匹配和替換發(fā)生在規(guī)則中所有變量和函數(shù)引用展開之后,變量和函數(shù)的展開一般發(fā)生在make讀取Makefile時(shí)师溅,而模式規(guī)則中的“ %”的匹配和替換則發(fā)生在make執(zhí)行時(shí)茅信。
文件名中的模式字符“ %”可以匹配任何非空字符串,除模式字符以外的部分要求一致墓臭。例如:“ %.c”匹配所有以“ .c”結(jié)尾的文件(匹配的文件名長(zhǎng)度最少為3個(gè)字母)蘸鲸,“ s%.c”匹配所有第一個(gè)字母為“ s”,而且必須以“ .c”結(jié)尾的文件窿锉,文件名長(zhǎng)度最小為5個(gè)字符(模式字符“ %”至少匹配一個(gè)字符)酌摇。同樣一個(gè)模式規(guī)則可以存在多個(gè)目標(biāo)。多目標(biāo)的模式規(guī)則和普通多目標(biāo)規(guī)則有些不同嗡载,普通多目標(biāo)規(guī)則的處理是將每一個(gè)目標(biāo)作為一個(gè)獨(dú)立的規(guī)則來(lái)處理妙痹,所以多個(gè)目標(biāo)就對(duì)應(yīng)多個(gè)獨(dú)立的規(guī)則(這些規(guī)則各自有自己的命令行,各個(gè)規(guī)則的命令行可能相同)鼻疮。但對(duì)于多目標(biāo)模式規(guī)則來(lái)說(shuō)怯伊,所有規(guī)則的目標(biāo)共同擁有依賴文件和規(guī)則的命令行,當(dāng)文件符合多個(gè)目標(biāo)模式中的任何一個(gè)時(shí),規(guī)則定義的命令就有可能將會(huì)執(zhí)行耿芹;因?yàn)槎鄠€(gè)目標(biāo)共同擁有規(guī)則的命令行崭篡,因此一次命令執(zhí)行之后,規(guī)則不會(huì)再去檢查是否需要重建符合其它模式的目標(biāo)吧秕。
#sample Makefile
Objects = foo.o bar.o
CFLAGS := -Wall
%x : CFLAGS += -g
%.o : CFLAGS += -O2
%.o %.x : %.c
$(CC) $(CFLAGS) $< -o $@
當(dāng)在命令行中執(zhí)行“ make foo.o foo.x”時(shí)琉闪,會(huì)看到只有一個(gè)文件“ foo.o”被創(chuàng)建了,同時(shí)make會(huì)提示“ foo.x”文件是最新的(其實(shí)“ foo.x”并沒(méi)有被創(chuàng)建)砸彬。
6.2 自動(dòng)化變量
6.2.1 $@
表示規(guī)則的目標(biāo)文件名颠毙。如果目標(biāo)是一個(gè)文檔文件( Linux中,一般稱.a文件為文檔文件砂碉,也稱為靜態(tài)庫(kù)文件)蛀蜜,那么它代表這個(gè)文檔的文件名。在多目標(biāo)模式規(guī)則中增蹭,它代表的是哪個(gè)觸發(fā)規(guī)則被執(zhí)行的目標(biāo)文件名滴某。
6.2.2 $%
當(dāng)規(guī)則的目標(biāo)文件是一個(gè)靜態(tài)庫(kù)文件時(shí),代表靜態(tài)庫(kù)的一個(gè)成員名滋迈。例如霎奢,規(guī)則的目標(biāo)是“ foo.a(bar.o)”,那么饼灿,“ $%” 的值就為“ bar.o”幕侠,“ $@”的值為“ foo.a”。如果目標(biāo)不是靜態(tài)庫(kù)文件碍彭,其值為空橙依。
6.2.3 $<
規(guī)則的第一個(gè)依賴文件名。如果是一個(gè)目標(biāo)文件使用隱含規(guī)則來(lái)重建硕旗,則它代表由隱含規(guī)則加入的第一個(gè)依賴文件窗骑。
6.2.4 $?
所有比目標(biāo)文件更新的依賴文件列表,空格分割漆枚。如果目標(biāo)是靜態(tài)庫(kù)文件名创译,代表的是庫(kù)成員( .o文件)。
6.2.5 $^
規(guī)則的所有依賴文件列表墙基,使用空格分隔软族。如果目標(biāo)是靜態(tài)庫(kù)文件,它所代表的只能是所有庫(kù)成員( .o文件)名残制。一個(gè)文件可重復(fù)的出現(xiàn)在目標(biāo)的依賴中立砸,變量“ $^”只記錄它的一次引用情況。就是說(shuō)變量“ $^”會(huì)去掉重復(fù)的依賴文件初茶。
6.2.6 $+
類似“ $^”颗祝,但是它保留了依賴文件中重復(fù)出現(xiàn)的文件。主要用在程序鏈接時(shí)庫(kù)的交叉引用場(chǎng)合。
6.2.7 $*
在模式規(guī)則和靜態(tài)模式規(guī)則中螺戳,代表“莖”搁宾。“莖”是目標(biāo)模式中“ %”所代表的部分(當(dāng)文件名中存在目錄時(shí)倔幼,“莖”也包含目錄(斜杠之前)部分盖腿,可參考 10.5.4模式的匹配 一小節(jié))。
例如:文件“ dir/a.foo.b”损同,當(dāng)目標(biāo)的模式為“ a.%.b”時(shí)翩腐,“ $*”的值為“ dir/a.foo”「嗳迹“莖”對(duì)于構(gòu)造相關(guān)文件名非常有用茂卦。