學(xué)習(xí)筆記之Makefile規(guī)則



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)合:

  1. 可以用在規(guī)則的目標(biāo)亲澡、依賴中, make 在讀取 Makefile 時(shí)會(huì)自動(dòng)對(duì)其進(jìn)行匹配處理(通配符展開);
  2. 可出現(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)文件名非常有用茂卦。

注:關(guān)于Makefile更詳細(xì)的信息請(qǐng)參考"GNU_make"文檔
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市蹄梢,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌富俄,老刑警劉巖禁炒,帶你破解...
    沈念sama閱讀 212,080評(píng)論 6 493
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異霍比,居然都是意外死亡幕袱,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,422評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門悠瞬,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)们豌,“玉大人,你說(shuō)我怎么就攤上這事浅妆⊥” “怎么了?”我有些...
    開封第一講書人閱讀 157,630評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵凌外,是天一觀的道長(zhǎng)辩尊。 經(jīng)常有香客問(wèn)我,道長(zhǎng)康辑,這世上最難降的妖魔是什么摄欲? 我笑而不...
    開封第一講書人閱讀 56,554評(píng)論 1 284
  • 正文 為了忘掉前任,我火速辦了婚禮疮薇,結(jié)果婚禮上胸墙,老公的妹妹穿的比我還像新娘。我一直安慰自己按咒,他們只是感情好迟隅,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,662評(píng)論 6 386
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般玻淑。 火紅的嫁衣襯著肌膚如雪嗽冒。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,856評(píng)論 1 290
  • 那天补履,我揣著相機(jī)與錄音添坊,去河邊找鬼。 笑死箫锤,一個(gè)胖子當(dāng)著我的面吹牛贬蛙,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播谚攒,決...
    沈念sama閱讀 39,014評(píng)論 3 408
  • 文/蒼蘭香墨 我猛地睜開眼阳准,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了馏臭?” 一聲冷哼從身側(cè)響起野蝇,我...
    開封第一講書人閱讀 37,752評(píng)論 0 268
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎括儒,沒(méi)想到半個(gè)月后绕沈,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,212評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡帮寻,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,541評(píng)論 2 327
  • 正文 我和宋清朗相戀三年乍狐,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片固逗。...
    茶點(diǎn)故事閱讀 38,687評(píng)論 1 341
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡浅蚪,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出烫罩,到底是詐尸還是另有隱情惜傲,我是刑警寧澤,帶...
    沈念sama閱讀 34,347評(píng)論 4 331
  • 正文 年R本政府宣布贝攒,位于F島的核電站操漠,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏饿这。R本人自食惡果不足惜浊伙,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,973評(píng)論 3 315
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望长捧。 院中可真熱鬧嚣鄙,春花似錦、人聲如沸串结。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,777評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至卧蜓,卻和暖如春帐要,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背弥奸。 一陣腳步聲響...
    開封第一講書人閱讀 32,006評(píng)論 1 266
  • 我被黑心中介騙來(lái)泰國(guó)打工榨惠, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人盛霎。 一個(gè)月前我還...
    沈念sama閱讀 46,406評(píng)論 2 360
  • 正文 我出身青樓赠橙,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親愤炸。 傳聞我的和親對(duì)象是個(gè)殘疾皇子期揪,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,576評(píng)論 2 349

推薦閱讀更多精彩內(nèi)容

  • 來(lái)自陳浩的一片老文,但絕對(duì)營(yíng)養(yǎng)规个。 示例工程:3 個(gè)頭文件*.h凤薛,和 8 個(gè) C 文件*.c。 初 編譯過(guò)程诞仓,源文件...
    周筱魯閱讀 4,690評(píng)論 0 17
  • 1.前言 在Makefile中缤苫,規(guī)則描述了用什么命令生成一個(gè)文件,該文件被稱為規(guī)則的目標(biāo)狂芋,生成"目標(biāo)"的方式就是規(guī)...
    tianyl閱讀 3,576評(píng)論 0 1
  • makefile關(guān)系到整個(gè)工程的編譯規(guī)則榨馁,一個(gè)工程中的源文件不計(jì)其數(shù)憨栽,按其類型帜矾、功能、模塊分別放在若干的目錄當(dāng)中屑柔,...
    Joe_HUST閱讀 1,876評(píng)論 0 3
  • 1.Makefile規(guī)范 target 這 一 個(gè) 或 多 個(gè) 的 目 標(biāo) 文 件 依 賴 于prerequisi...
    G風(fēng)閱讀 1,885評(píng)論 0 3
  • @(linux 編程)[開發(fā)技能, 工具使用] What is GNU Make Make 是控制工程中通過(guò)源碼生...
    orientlu閱讀 11,325評(píng)論 0 26