本文章將對make與makefile進行一些基礎的講解。
假設我們要建造一座房子,建造過程涉及很多步驟,比如打地基、砌墻、安裝門窗、粉刷墻壁等。每個步驟都有先后順序,并且有些步驟可能依賴于其他步驟的完成。比如,你必須先打好地基才能砌墻,必須先砌好墻才能安裝門窗。這時候,你需要一個詳細的施工流程表,告訴工人每一步該做什么,以及在什么條件下可以進行下一步。make
?和?makefile
?就像是這個施工流程表。
一、什么是?make
?和?makefile
- ??
makefile
??:是一個文本文件,里面包含了一系列的規則,這些規則定義了如何從源文件生成目標文件,以及各個目標文件之間的依賴關系。 - ??
make
??:是一個構建自動化工具,它會讀取?makefile
?中的規則,并根據這些規則來決定哪些文件需要重新編譯或構建。
二、makefile
?的基本結構
一個典型的?makefile
?包含以下幾個部分:
- ??目標(Target)??:你想要生成的東西,比如一個可執行文件或一個目標文件。
- ??依賴(Dependency)??:生成目標所需要的文件。
- ??命令(Command)??:為了生成目標需要執行的命令。
一個簡單的?makefile
?示例:
# 目標:生成可執行文件 main
main: main.o add.o sub.ogcc main.o add.o sub.o -o main# 目標:生成 main.o
main.o: main.cgcc -c main.c# 目標:生成 add.o
add.o: add.cgcc -c add.c# 目標:生成 sub.o
sub.o: sub.cgcc -c sub.c# 清理生成的文件
clean:rm -f main main.o add.o sub.o
解釋
-
??目標?
main
??:- ??依賴??:
main.o
、add.o
?和?sub.o
。 - ??命令??:
gcc main.o add.o sub.o -o main
。這個命令表示將?main.o
、add.o
?和?sub.o
?鏈接成一個可執行文件?main
。
- ??依賴??:
-
??目標?
main.o
??:- ??依賴??:
main.c
。 - ??命令??:
gcc -c main.c
。這個命令表示將?main.c
?編譯成目標文件?main.o
。
- ??依賴??:
-
??目標?
add.o
?和?sub.o
??:- 類似于?
main.o
,分別將?add.c
?和?sub.c
?編譯成目標文件。
- 類似于?
-
??目標?
clean
??:- ??命令??:
rm -f main main.o add.o sub.o
。這個命令用于清理生成的可執行文件和目標文件。
- ??命令??:
三、make
?的工作原理
當你運行?make
?命令時,make
?會讀取?makefile
?文件,并按照以下步驟工作:
- ??讀取?
makefile
??:make
?會解析?makefile
?中的規則,構建一個依賴圖。 - ??確定目標??:默認情況下,
make
?會嘗試生成?makefile
?中第一個目標(在這個例子中是?main
)。 - ??檢查依賴??:
make
?會檢查目標的依賴文件是否存在,以及這些依賴文件是否有更新。如果依賴文件不存在或比目標文件新,make
?會執行相應的命令來更新目標文件。(如何檢查的呢?) - ??執行命令??:
make
?會按照依賴圖的順序執行命令,生成最終的目標。
四、示例運行
假設你有以下文件:
main.c
add.c
sub.c
運行?make
?命令:
make
?會根據?makefile
?中的規則,依次編譯?main.c
、add.c
?和?sub.c
,然后將它們鏈接成可執行文件?main
。
如果你修改了?add.c
?文件,再次運行?make
:
make
?會檢測到?add.c
?文件有更新,只重新編譯?add.c
?成?add.o
,然后重新鏈接生成?main
。
如果你想清理生成的文件,可以運行:
make clean
make
?會執行?clean
?目標中的命令,刪除?main
、main.o
、add.o
?和?sub.o
?文件。
五、?.PHONY
在?makefile
?中,.PHONY
?是一個特殊的目標,用于聲明某些目標是“偽目標”。偽目標不是實際的文件,而是用于執行特定的命令或任務。使用?.PHONY
?可以避免與同名文件沖突,并且可以提高?make
?的執行效率。
1.為什么需要?.PHONY
- ??避免與文件名沖突??:如果有一個目標名與文件名相同,
make
?會誤認為該目標是文件,而不是一個任務。使用?.PHONY
?可以避免這種沖突。 - ??提高執行效率??:
make
?會檢查文件的時間戳來決定是否需要重新生成目標文件。對于偽目標,make
?不需要檢查時間戳,可以直接執行相應的命令,從而提高執行效率。 - ??明確意圖??:使用?
.PHONY
?可以明確告訴其他開發者,這個目標是一個虛擬的任務,而不是一個實際的文件。
2.如何使用?.PHONY
以下是一個簡單的?makefile
?示例,展示了如何使用?.PHONY
:
# 聲明偽目標
.PHONY: clean test# 默認目標
all: main# 生成可執行文件 main
main: main.o add.o sub.ogcc main.o add.o sub.o -o main# 生成 main.o
main.o: main.cgcc -c main.c# 生成 add.o
add.o: add.cgcc -c add.c# 生成 sub.o
sub.o: sub.cgcc -c sub.c# 清理生成的文件
clean:rm -f main main.o add.o sub.o# 運行測試
test:./mainecho "All tests passed!"
在這個示例中:
.PHONY: clean test
?聲明了?clean
?和?test
?是偽目標。clean
?目標用于清理生成的文件,它不生成任何實際的文件。test
?目標用于運行測試,它也不生成任何實際的文件。
示例解釋
1.聲明偽目標
.PHONY: clean test
這行代碼告訴?make
,clean
?和?test
?是偽目標,而不是實際的文件。即使當前目錄下存在名為?clean
?或?test
?的文件,make
?也會執行相應的命令。
2. 使用偽目標
-
??清理文件??:
make clean
這條命令會執行?
clean
?目標中的命令,刪除?main
、main.o
、add.o
?和?sub.o
?文件。 -
??運行測試??:
make test
這條命令會執行?
test
?目標中的命令,運行?main
?可執行文件,并輸出 "All tests passed!"。
3. 避免沖突
假設當前目錄下有一個名為?clean
?的文件,如果沒有使用?.PHONY
?聲明?clean
?為偽目標,make
?會認為?clean
?是一個文件,而不是一個任務。此時,運行?make clean
?不會執行任何命令,因為?clean
?文件已經存在,且沒有依賴關系需要更新。
通過使用?.PHONY
,可以避免這種沖突,確保?make clean
?總是執行清理命令。
.PHONY
?不僅可以用于常見的清理和測試任務,還可以用于其他任何不需要生成實際文件的任務。
- ??
.PHONY
?的作用??:聲明偽目標,避免與文件名沖突,提高執行效率,明確意圖。 - ??如何使用??:在?
makefile
?中使用?.PHONY
?關鍵字,后跟偽目標的名稱列表。 - ??常見用途??:清理文件、運行測試、生成文檔、打包發布、代碼風格檢查等。
- 偽目標總是會被執行,不會被攔截。(比如我們重復make會提示已經make了不讓我們make,但是如果我們把他搞成偽目標,那么就不會受此限制了)。
六、優點
- ??自動化??:
make
?可以自動處理文件之間的依賴關系,只重新編譯需要更新的文件,節省時間和資源。 - ??可維護性??:通過?
makefile
,你可以清晰地定義項目的構建流程,方便團隊協作和項目管理。 - ??靈活性??:
makefile
?支持復雜的規則和條件判斷,可以適應各種構建需求。
七、缺點
- ??維護成本??:隨著項目規模的增大,
makefile
?可能會變得非常復雜,維護起來比較困難。
八、總結
- ??
makefile
??:是一個包含構建規則的文本文件,定義了如何從源文件生成目標文件以及各個目標文件之間的依賴關系。 - ??
make
??:是一個構建自動化工具,讀取?makefile
?中的規則,并根據這些規則決定哪些文件需要重新編譯或構建。
通過?make
?和?makefile
,你可以高效地管理和構建項目,確保每次構建都是基于最新的文件狀態。