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

