Makefile的基本概念
GNU make最初是Unix系統(tǒng)下的一個(gè)工具,設(shè)計(jì)之初是為了維護(hù)C程序文件不必要的重新編譯,他是一個(gè)自動(dòng)生成和維護(hù)目標(biāo)程序的工具
make是一個(gè)解釋Makefile文件中指令的命令工具,其最基本的功能就是通過Makefile文件來描述源程序之間的相互關(guān)系并自動(dòng)維護(hù)編譯工作,他會(huì)告知系統(tǒng)以何種方式編譯和鏈接程序。
Makefile寫好之后,每次改變了某些源文件只要執(zhí)行make命令($ make)
所有必要的重新編譯將執(zhí)行,make程序利用Makefile中的數(shù)據(jù)和每個(gè)文件的最后修改時(shí)間來確定哪個(gè)文件需要更新,對(duì)于需要更新的文件,make程序執(zhí)行Makefile數(shù)據(jù)中的定義的命令來更新。
GNU make的主要功能是讀進(jìn)一個(gè)文本文件Makefile,并根據(jù)Makefile的內(nèi)容執(zhí)行一系列工作。
Makefile的默認(rèn)文件名為GNUmakefile、makefile或Makefile,當(dāng)然也可以在make命令行中指定別的文件名。如果不特別指定,make命令在執(zhí)行時(shí),將按照順序查找默認(rèn)的makefile文件。
Makefile是一個(gè)文本形式的數(shù)據(jù)庫(kù)文件,其中包含了一些規(guī)則,來告訴make處理哪些文件以及如何處理這些文件。
這些規(guī)則主要是描述哪些文件(target目標(biāo)文件)是從哪些別的文件(dependency依賴文件)中產(chǎn)生而來的,以及用什么命令(command)來執(zhí)行這個(gè)過程
依靠這些信息,make會(huì)對(duì)磁盤上的文件進(jìn)行檢查,如果目標(biāo)文件的生成或被改動(dòng)時(shí)的時(shí)間(文件的時(shí)間戳)至少比它的一個(gè)依賴文件還舊的話,make就執(zhí)行相應(yīng)的命令,已更新目標(biāo)文件。目標(biāo)文件不一定是最后的可執(zhí)行文件,可以是任何一個(gè)中間文件并可以作為其他目標(biāo)文件的依賴文件。
GNU make工作流程
- 查找當(dāng)前目錄下的Makefile文件
- 初始化文件中的變量
- 分析Makefile中的所有規(guī)則
- 為所有的目標(biāo)文件創(chuàng)建依賴關(guān)系
- 根據(jù)依賴關(guān)系,決定哪些文件重新生成
- 執(zhí)行生成命令
一個(gè)Makefile文件主要有一系列規(guī)則,每條規(guī)則都必須包含以下內(nèi)容:
- 一個(gè)目標(biāo)(target),即make最終需要?jiǎng)?chuàng)建的文件,如可執(zhí)行文件或目標(biāo)文件,目標(biāo)也可以是要執(zhí)行的動(dòng)作,如clean
- 一個(gè)或多個(gè)依賴文件(dependency)列表,通常是編譯目標(biāo)文件所需要的其他文件
- 一系列命令(command),是make執(zhí)行的動(dòng)作,通常是把指定的相關(guān)文件編譯成目標(biāo)文件的編譯命令,每個(gè)命令占一行,并且每個(gè)命令的起始字符必須為Tab字符。

圖中,藍(lán)綠色的為目標(biāo),白色的為依賴文件,紅色的為命令,藍(lán)色的為注釋





make命令
標(biāo)準(zhǔn)形式:$ make [選項(xiàng)] [宏定義] [目標(biāo)文件]
- 常用選項(xiàng)
-
-f:file,指定Makefile的文件名
-

-
-n:打印出所有的執(zhí)行命令,但事實(shí)上不執(zhí)行這些命令
顯示命令,但不執(zhí)行 -s:在執(zhí)行時(shí)不打印命令名

-
-w:如果在make執(zhí)行時(shí)要改變目錄,則打印當(dāng)前的執(zhí)行目錄 -
-d:打印調(diào)試信息 -
-I <dirname>:指定所用Makefile所在的目錄 -
-h:help文檔
Makefile目標(biāo)文件
參數(shù)“目標(biāo)文件”,對(duì)于make命令來說,也是一個(gè)可選項(xiàng),如果在執(zhí)行make命令時(shí)帶有該參數(shù),可以輸入一下命令:$ make 目標(biāo)文件
如果省略目標(biāo)文件參數(shù),就會(huì)生成Makefile中定義的第一個(gè)目標(biāo)文件。因此,常見的用法就是經(jīng)常把用戶最終想要的目標(biāo)文件(可執(zhí)行程序)放在Makefile文件的首要位置,這樣用戶只需要執(zhí)行make命令即可。

Makefile規(guī)則語(yǔ)法
- 語(yǔ)法規(guī)則
#注釋
目標(biāo)文件:依賴文件列表
<Tab>命令列表
#.......
注釋:和shell腳本一樣,Makefile語(yǔ)句行的注釋采用"#"符號(hào)
目標(biāo):目標(biāo)文件的列表,通常指程序編譯過程中生成的目標(biāo)文件(.o文件)或最終的可執(zhí)行程序,有時(shí)也可以是要執(zhí)行的動(dòng)作,如“clean”這樣的目標(biāo)
Makefile中變量的使用
Makefile中的變量就像一個(gè)環(huán)境變量。事實(shí)上,環(huán)境變量在make中也被解釋為make的變量。這些變量對(duì)大小寫敏感,一般使用大寫字母。幾乎可以從任何地方引用定義的變量。
- 變量的主要作用:
- 保存文件名列表。
在前面的例子里,作為依賴文件的一些目標(biāo)文件出現(xiàn)在可執(zhí)行文件的規(guī)則中,而在這個(gè)規(guī)則的命令行里同樣包含這些文件并傳遞個(gè)gcc作為命令參數(shù)。如果使用一個(gè)變量來保存所有的目標(biāo)文件名則可以方便的加入新的目標(biāo)文件而且不易出錯(cuò)。 - 保存可執(zhí)行命令名(如編譯器)
在不同的Linux系統(tǒng)中,存在著很多相似的編譯器系統(tǒng),這些系統(tǒng)在某些地方會(huì)有細(xì)微的差別,如果項(xiàng)目被用在一個(gè)非gcc的系統(tǒng)里,則必須將所有出現(xiàn)編譯器名的地方改成用新的編譯器名。但是如果使用一個(gè)變量來替代編譯器名,那么只需要修改變量的值。其他所有地方的命令就都改變了。(有點(diǎn)類似與C/C++中的typedef,程序中將int定義為num,后期需要更換為short或者double,只需要修改typedef的值,而不需要修改所有的變量定義) - 保存編譯器的參數(shù)
在很多源代碼編譯時(shí),gcc需要很長(zhǎng)的參數(shù)選項(xiàng),在很多情況下,所有的編譯器命令使用一組相同的選項(xiàng),如果把這組選項(xiàng)使用一個(gè)變量代表,那么可以把這個(gè)變量放在所有的引用編譯器的地方,當(dāng)藥修改選項(xiàng)的時(shí)候,只需要修改一次這個(gè)變量的內(nèi)容即可。
- 保存文件名列表。
- Makefile文件中變量的使用
Makefile中的變量是一個(gè)用文本串在Makefile中定義的,這個(gè)文本串就是變量的值。只要在一行開始寫下這個(gè)變量的名字,后面跟一個(gè)“=”好,以及要設(shè)定這個(gè)變量的值,即可定義變量,下面是定義變量的語(yǔ)法:VAENAME=string
使用是,把變量用括號(hào)括起來,并在前面加上“$”符號(hào),就可以引用變量的值:$(VARNAME)


make工具還有一些特殊的內(nèi)部變量,根據(jù)每一個(gè)規(guī)則內(nèi)容定義。
$@:指代當(dāng)前規(guī)則下的目標(biāo)文件列表$<:指代以來文件列表中的第一個(gè)依賴文件$^:指代以來文件中的所有依賴文件$?:紙袋以來列表中新于對(duì)應(yīng)目標(biāo)文件的列表

Make自動(dòng)推導(dǎo)
GNU的make功能很強(qiáng)大,它可以自動(dòng)推導(dǎo)文件以及文件的依賴關(guān)系后面的命令,浴室我們就沒必要去為每一個(gè)".o"文件后都寫上類似的命令,因?yàn)?,我們的make會(huì)自動(dòng)識(shí)別,并自己推導(dǎo)命令。
只要make看到一個(gè).o文件,他就會(huì)自動(dòng)的把“.c”文件加在依賴關(guān)系中,如果馬克找到一個(gè)test.o,那么test.c就會(huì)是test.o的依賴文件,并且在gcc -c test.c也會(huì)被推導(dǎo)出來。


