Linux自動(dòng)化構(gòu)建工具-make/Make?le使用解讀
Make/Makefile完全指南
一、引言
在軟件開(kāi)發(fā)的世界里,構(gòu)建項(xiàng)目是一項(xiàng)重復(fù)且繁瑣的工作。
尤其是對(duì)于大型項(xiàng)目,編譯源文件、鏈接庫(kù)、生成可執(zhí)行文件等操作可能涉及成百上千個(gè)文件,手動(dòng)管理這些過(guò)程幾乎是不可能的。
這時(shí),自動(dòng)化構(gòu)建工具就顯得尤為重要。
二、Make/Makefile 基礎(chǔ)概念
1. 什么是 Make?
Make 是一個(gè)自動(dòng)化構(gòu)建工具,它根據(jù) Makefile 中定義的規(guī)則來(lái)編譯和鏈接程序。
Make 的核心思想是:只重新構(gòu)建那些發(fā)生了變化的文件,從而大大提高構(gòu)建效率。
2. 什么是 Makefile?
Makefile 是一個(gè)文本文件,包含了一系列規(guī)則,告訴 Make 如何構(gòu)建你的項(xiàng)目。
一個(gè)簡(jiǎn)單的 Makefile 可能包含源文件、目標(biāo)文件、依賴關(guān)系以及構(gòu)建命令等信息。
3. 為什么需要 Make/Makefile?
- 提高效率:自動(dòng)檢測(cè)文件變化,只重新編譯必要的文件。
- 簡(jiǎn)化流程:將復(fù)雜的構(gòu)建過(guò)程抽象為簡(jiǎn)單的命令。
- 便于維護(hù):項(xiàng)目結(jié)構(gòu)和構(gòu)建規(guī)則清晰明了。
三、Makefile 基本語(yǔ)法
1. 規(guī)則的基本格式
Makefile 由一系列規(guī)則組成,每個(gè)規(guī)則的基本格式如下:
target: dependencies
command1
command2
...
- target:目標(biāo)文件或操作名稱。
- dependencies:目標(biāo)文件所依賴的文件或目標(biāo)。
- command:構(gòu)建目標(biāo)所需執(zhí)行的命令(必須以 Tab 鍵開(kāi)頭)。
2. 簡(jiǎn)單示例
下面是一個(gè)簡(jiǎn)單的 Makefile 示例,用于編譯一個(gè) C 程序:
hello: hello.c
gcc -o hello hello.c
這個(gè) Makefile 定義了一個(gè)規(guī)則:目標(biāo)是生成可執(zhí)行文件 hello,它依賴于 hello.c 文件,構(gòu)建命令是使用 gcc 編譯 hello.c。
3. 變量的使用
在 Makefile 中,可以使用變量來(lái)簡(jiǎn)化代碼。例如:
CC = gcc
CFLAGS = -Wall -g
hello: hello.c
$(CC) $(CFLAGS) -o hello hello.c
這里定義了兩個(gè)變量:CC 表示編譯器,CFLAGS 表示編譯選項(xiàng)。使用 $(變量名) 來(lái)引用變量。
4. 自動(dòng)變量
Make 提供了一些自動(dòng)變量,用于簡(jiǎn)化規(guī)則的編寫(xiě):
$@:表示當(dāng)前目標(biāo)。$<:表示第一個(gè)依賴文件。$^:表示所有依賴文件。
使用自動(dòng)變量,上面的示例可以改寫(xiě)為:
CC = gcc
CFLAGS = -Wall -g
hello: hello.c
$(CC) $(CFLAGS) -o $@ $<
四、Makefile 高級(jí)特性
1. 模式規(guī)則
模式規(guī)則允許定義通用的編譯規(guī)則,適用于一類文件。例如:
CC = gcc
CFLAGS = -Wall -g
%.o: %.c
$(CC) $(CFLAGS) -c $< -o $@
這個(gè)規(guī)則表示如何從 .c 文件生成 .o 文件,適用于所有的 C 源文件。
2. 靜態(tài)模式規(guī)則
靜態(tài)模式規(guī)則用于為一組目標(biāo)定義相同的構(gòu)建規(guī)則。例如:
objects = foo.o bar.o baz.o
$(objects): %.o: %.c
$(CC) $(CFLAGS) -c $< -o $@
這個(gè)規(guī)則表示如何從對(duì)應(yīng)的 .c 文件生成 foo.o、bar.o 和 baz.o。
3. 函數(shù)的使用
Makefile 提供了一些內(nèi)置函數(shù),用于處理文件列表、字符串等。例如:
SRCS = $(wildcard *.c) OBJS = $(patsubst %.c,%.o,$(SRCS)) all: $(OBJS)
wildcard函數(shù)用于獲取所有匹配的文件列表。patsubst函數(shù)用于模式替換。
4. 偽目標(biāo)
偽目標(biāo)所修飾的依賴關(guān)系,即使在執(zhí)行過(guò)一次后,仍然會(huì)被強(qiáng)制執(zhí)行。
偽目標(biāo)不是真正的文件名,而是一種執(zhí)行命令的方式。例如:
.PHONY: clean
clean:
rm -f *.o hello
.PHONY 聲明 clean 為偽目標(biāo),這樣即使當(dāng)前目錄下存在名為 clean 的文件,Make 也會(huì)執(zhí)行對(duì)應(yīng)的命令。
偽目標(biāo)詳細(xì)說(shuō)明
stat
在說(shuō)偽目標(biāo)之前,就要談到stat這個(gè)指令,stat 命令用于顯示文件或文件系統(tǒng)的詳細(xì)信息,包括文件類型、權(quán)限、時(shí)間戳、inode 信息等。
時(shí)間戳的區(qū)別:
stat 輸出中包含三種時(shí)間戳:
- Access (atime):文件最后被訪問(wèn)的時(shí)間(如 cat、less 命令讀取文件)。一般來(lái)說(shuō),為了提高效率,會(huì)在執(zhí)行幾次modify 和 change 后 access 才會(huì)改變。
- Modify (mtime):文件內(nèi)容最后被修改的時(shí)間(如 vim 編輯文件后保存)。修改文件內(nèi)容時(shí)間
- Change (ctime):文件元數(shù)據(jù)(如權(quán)限、所有者)最后被更改的時(shí)間。修改文件屬性時(shí)間
** 在我們使用make指令時(shí),當(dāng)使用一次之后,有時(shí)會(huì)顯示不能夠再次使用,這是因?yàn)橹挥性谠次募罱男薷臅r(shí)間比可執(zhí)行文件要老時(shí),才能夠執(zhí)行 **
只需要比較可執(zhí)行程序最近的修改時(shí)間和源文件最近的修改時(shí)間(使用時(shí)間戳比較) .exe 新于 .c 源文件,不需要重新編譯 .exe 老于 .c 源文件,需要重新編譯
所以說(shuō),為了不受修改時(shí)間對(duì)指令的影響,就引入了偽目標(biāo)這一概念。
偽目標(biāo)
在 Makefile 里,偽目標(biāo)(phony target)并非代表實(shí)際的文件,它的作用是把多個(gè)命令組織起來(lái),達(dá)成特定的構(gòu)建目的。
當(dāng)你執(zhí)行 make 命令并帶上偽目標(biāo)名稱時(shí),Make 會(huì)直接執(zhí)行該偽目標(biāo)所關(guān)聯(lián)的命令,而不會(huì)去檢查是否存在同名文件,也不會(huì)考慮文件的更新時(shí)間。
偽目標(biāo)的關(guān)鍵特性
- 不對(duì)應(yīng)實(shí)際文件:偽目標(biāo)的名稱在文件系統(tǒng)中找不到對(duì)應(yīng)的文件。
- 強(qiáng)制執(zhí)行命令:不管文件是否有更新,Make 都會(huì)執(zhí)行偽目標(biāo)的命令。
- 避免命名沖突:要是目錄中存在和目標(biāo)同名的文件,使用偽目標(biāo)就能防止規(guī)則被錯(cuò)誤觸發(fā)。
為什么需要 .PHONY 聲明?
在 Makefile 中,使用 .PHONY 來(lái)聲明偽目標(biāo)是很有必要的。如果不這樣做,當(dāng)目錄中存在與目標(biāo)同名的文件時(shí),Make 可能會(huì)認(rèn)為目標(biāo)已經(jīng)是最新的,從而不會(huì)執(zhí)行相應(yīng)的命令。
例如,要是沒(méi)有 .PHONY 聲明:
makefile
clean:
rm -f *.o
當(dāng)目錄中存在名為 clean 的文件時(shí),執(zhí)行 make clean 命令不會(huì)刪除任何 .o 文件,因?yàn)?Make 覺(jué)得目標(biāo) clean 已經(jīng)是最新?tīng)顟B(tài)了。
而加上 .PHONY 聲明后:
makefile
.PHONY: clean
clean:
rm -f *.o
無(wú)論是否存在 clean 文件,Make 都會(huì)執(zhí)行 rm -f *.o 命令。
五、Makefile 實(shí)戰(zhàn)技巧
1. 調(diào)試技巧
- 使用
make -n查看將要執(zhí)行的命令,但不實(shí)際執(zhí)行。 - 使用
make -d顯示詳細(xì)的調(diào)試信息。 - 在命令前加
@可以不顯示該命令本身,只顯示結(jié)果。 - make會(huì)一層又一層地去找文件的依賴關(guān)系,直到最終編譯出第一個(gè)目標(biāo)文件。在找尋的過(guò)程中,如果出現(xiàn)錯(cuò)誤,比如最后被依賴的文件找不到,那么make就會(huì)直接退出,并報(bào)錯(cuò),而對(duì)于所定義的命令的錯(cuò)誤,或是編譯不成功,make根本不理。make只管文件的依賴性,即,如果在我找了依賴關(guān)系之后,冒號(hào)后面的文件還是不在,就不會(huì)工作了。
- 單獨(dú)使用make指令時(shí),會(huì)自動(dòng)執(zhí)行makefile文件的第一條依賴關(guān)系。
2. 并行構(gòu)建
使用 make -jN 可以并行執(zhí)行 N 個(gè)任務(wù),加快構(gòu)建速度。例如:
make -j4 # 并行執(zhí)行 4 個(gè)任務(wù)
3. 條件編譯
可以在 Makefile 中使用條件語(yǔ)句,根據(jù)不同的條件執(zhí)行不同的命令。例如:
ifeq ($(DEBUG), 1) CFLAGS += -DDEBUG -g endif
總結(jié)
Make/Makefile 是 Linux 系統(tǒng)中強(qiáng)大的自動(dòng)化構(gòu)建工具,通過(guò)合理使用 Makefile 的各種特性,可以高效地管理復(fù)雜項(xiàng)目的構(gòu)建過(guò)程。
本文介紹了 Make/Makefile 的基礎(chǔ)知識(shí)、語(yǔ)法、高級(jí)特性以及在大型項(xiàng)目中的組織方法和實(shí)戰(zhàn)技巧。掌握這些內(nèi)容后,你將能夠編寫(xiě)高效、靈活的 Makefile,提高軟件開(kāi)發(fā)效率。
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
jps查看進(jìn)程無(wú)法顯示的問(wèn)題及解決
文章描述了使用jps命令查看進(jìn)程無(wú)法顯示的問(wèn)題,并提供了解決方案,解決方法包括切換到tmp目錄,使用ll命令查看子目錄,找到并修改權(quán)限為755的"hsperfdata_[用戶名]"和"hsperfdata_root"目錄2025-01-01
Centos6.5搭建java開(kāi)發(fā)環(huán)境配置詳解
這篇文章主要介紹了Centos6.5搭建java開(kāi)發(fā)環(huán)境配置詳解,非常具有實(shí)用價(jià)值,需要的朋友可以參考下。2016-12-12
linux下安裝memcached_動(dòng)力節(jié)點(diǎn)Java學(xué)院整理
這篇文章主要給大家介紹了關(guān)于在linux下安裝memcached的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來(lái)一起看看吧。2017-08-08
Linux內(nèi)核設(shè)備驅(qū)動(dòng)之虛擬文件系統(tǒng)筆記整理
今天小編就為大家分享一篇關(guān)于Linux內(nèi)核設(shè)備驅(qū)動(dòng)之虛擬文件系統(tǒng)筆記整理,小編覺(jué)得內(nèi)容挺不錯(cuò)的,現(xiàn)在分享給大家,具有很好的參考價(jià)值,需要的朋友一起跟隨小編來(lái)看看吧2018-12-12

