make
?—— 項(xiàng)目的關(guān)節(jié)
一個(gè)中型或大型項(xiàng)目,通常由許多文件組成模塊,又由各個(gè)模塊組成整個(gè)系統(tǒng),將各個(gè)文件、模塊構(gòu)建為系統(tǒng)的方式,一直是項(xiàng)目管理中的要點(diǎn)。make
是一個(gè)傳統(tǒng)——但是流行的構(gòu)建工具,Makefile
是其定義規(guī)則的文件,其中定義的規(guī)則就像關(guān)節(jié),將項(xiàng)目中的各部分靈活而有序地組織在一起。
基本語(yǔ)法
Makefile
的核心是規(guī)則,其由一系列規(guī)則組成,每個(gè)規(guī)則的基本語(yǔ)法如下:
target:?prerequisites
????recipe
-
target:目標(biāo),即要?jiǎng)?chuàng)建或更新的文件,也可以是一個(gè)偽目標(biāo)(不對(duì)應(yīng)實(shí)際文件,用于執(zhí)行特定操作)。 -
prerequisites:依賴項(xiàng),是目標(biāo)所依賴的文件或其他目標(biāo)。當(dāng)依賴項(xiàng)中的任何一個(gè)發(fā)生改變時(shí), make
會(huì)認(rèn)為目標(biāo)需要更新,并執(zhí)行對(duì)應(yīng)的規(guī)則命令。 -
recipe:規(guī)則命令序列,是為了創(chuàng)建或更新目標(biāo)而需要執(zhí)行的命令,必須以制表符(Tab)開(kāi)頭。
除此之外,Makefile
還有一些作為腳本必要且實(shí)用的功能,以下的實(shí)際案例將進(jìn)一步說(shuō)明。
C語(yǔ)言項(xiàng)目構(gòu)建案例
CC?=?gcc
CFLAGS?=?-Wall?-g
all:?myprogram
myprogram:?main.o?utils.o
????$(CC)?$(CFLAGS)?-o?myprogram?main.o?utils.o
main.o:?main.c?utils.h
????$(CC)?$(CFLAGS)?-c?main.c
utils.o:?utils.c?utils.h
????$(CC)?$(CFLAGS)?-c?utils.c
clean:
????rm?-f?*.o?myprogram
以上Makefile
編寫(xiě)了5條規(guī)則。
1. all
make
默認(rèn)會(huì)執(zhí)行Makefile
里首個(gè)規(guī)則的目標(biāo),此目標(biāo)通常被稱作默認(rèn)目標(biāo)。一般而言,會(huì)把all
作為默認(rèn)目標(biāo),該目標(biāo)依賴于項(xiàng)目中的其他主要目標(biāo),以此來(lái)確保所有必要的文件都能被構(gòu)建。
make
也可手動(dòng)指定構(gòu)建目標(biāo),如:
make?all
make?clean
make?main.o
2. myprogram
myprogram
目標(biāo)有2個(gè)依賴項(xiàng)main.o
和utils.o
,若依賴項(xiàng)已構(gòu)建完畢,則會(huì)執(zhí)行recipe
部分所定義的命令,將.o
文件通過(guò)gcc
鏈接為可執(zhí)行文件myprogram
。
對(duì)于每個(gè)目標(biāo),make
會(huì)檢查其依賴項(xiàng)是否存在或者是否有更新。若依賴項(xiàng)不存在,make
會(huì)嘗試構(gòu)建這些依賴項(xiàng);若依賴項(xiàng)的修改時(shí)間比目標(biāo)新,make
會(huì)認(rèn)為目標(biāo)需要更新,進(jìn)而執(zhí)行該目標(biāo)對(duì)應(yīng)的規(guī)則命令。
3. main.o
若main.c
或utils.h
文件有更新,則根據(jù)recipe
定義的命令,通過(guò)gcc
編譯生成main.o
。
4. utils.o
同main.o
。
5. clean
目標(biāo)可以是文件,也可以是一個(gè)偽目標(biāo),偽目標(biāo)可通過(guò).PHONY
聲明,確保即使存在同名文件,make
也會(huì)執(zhí)行對(duì)應(yīng)的規(guī)則。(案例中由于不存在與目標(biāo)all/clean同名文件,故省略.PHONY
聲明)
.PHONY:?all?clean
all:?myprogram
clean:
????rm?-f?*.o?myprogram
當(dāng)執(zhí)行偽目標(biāo)時(shí),make
會(huì)直接執(zhí)行該目標(biāo)對(duì)應(yīng)的規(guī)則命令,而不會(huì)檢查文件的修改時(shí)間.
更進(jìn)一步
Makefile
作為一種構(gòu)建腳本,可以像shell
那樣,在recipe
中直接編寫(xiě)命令,比如調(diào)用Python
腳本。
C
和Python
混合項(xiàng)目案例
假設(shè)項(xiàng)目中有一個(gè)C程序和一個(gè)Python腳本,C程序生成的數(shù)據(jù)會(huì)被Python腳本處理。
project/
├── main.c
├── process.py
└── Makefile
#?定義編譯器和編譯選項(xiàng)
CC?=?gcc
CFLAGS?=?-Wall?-g
#?定義目標(biāo)
all:?data.txt?result.txt
#?編譯?C?程序并生成數(shù)據(jù)文件
data.txt:?main
????./main?>?data.txt
main:?main.c
????$(CC)?$(CFLAGS)?-o?main?main.c
#?使用?Python?腳本處理數(shù)據(jù)文件
result.txt:?data.txt?process.py
????python3?process.py?data.txt?>?result.txt
#?清理生成的文件
clean:
????rm?-f?main?data.txt?result.txt
結(jié)語(yǔ)
Makefile
還有一些常用的高級(jí)語(yǔ)法,后續(xù)有機(jī)會(huì)我會(huì)再開(kāi)一篇文章介紹。感興趣的朋友可以點(diǎn)贊支持哦~
參考資料
GNU make:?https://www.gnu.org/software/make/manual/make.html