Linux操作系統從入門到實戰(九)Linux開發工具(中)自動化構建-make/Makefile
- 前言
- 一、 make/Makefile是什么?
- 1. 我們先想個問題:手動編譯代碼有多麻煩?
- 2. 為了解決麻煩,才有了自動化工具
- 3. 什么是 Makefile ?
- 4. 什么是 make ?
- 二、如何使用 make/Makefile
- 1. 如何創建第一個Makefile?
- (1) 創建源文件
- (2) 創建Makefile文件
- (3) 編寫Makefile規則
- (4) 執行make命令
- 2. 依賴關系與命令
- (1) 依賴關系
- (2) make的執行邏輯
- (3) 為什么需要依賴關系?
- 3. 如何清理編譯結果?
- (1) 添加clean目標
- (2) 執行清理命令
- (3) .PHONY 標簽的作用
- 4. Makefile的執行規則
- (1) 默認執行第一個目標
- (2) 如何執行其他目標?
- (3) 多個目標的執行順序
- 5. 常見錯誤與注意事項
- (1) 命令行必須以Tab鍵開頭
- (2) 文件名大小寫敏感
- 三、偽目標是什么,為什么偽目標總被執行?
- 1. make如何判斷是否需要重新編譯?
- 2. 什么是偽目標(.PHONY)?
- (1)定義:
- (2) 常見用途:
- 3. 為什么偽目標總是被執行?
- (1)核心原因:
- (2) 對比實驗:
- 4. 為什么需要偽目標?
- (1) 避免與文件沖突
- (2) 強制執行命令
- 5. 常見偽目標示例
- 1. clean目標(最常見)
- 2. all目標(批量編譯多個程序)
- 3. install目標(安裝程序到系統)
前言
- 前面的博客里我們講解了vim編譯,g++/gcc編譯的步驟和動靜態鏈接與庫的相關知識
- 接下來我們繼續講解Linux開發工具自動化構建-make/Makefile
我的個人主頁,歡迎來閱讀我的其他文章
https://blog.csdn.net/2402_83322742?spm=1011.2415.3001.5343
我的Linux知識文章專欄
歡迎來閱讀指出不足
https://blog.csdn.net/2402_83322742/category_12879535.html?spm=1001.2014.3001.5482
一、 make/Makefile是什么?
1. 我們先想個問題:手動編譯代碼有多麻煩?
- 假設你寫了一個小項目,里面有好幾個
.c
源文件(比如a.c
、b.c
、main.c
)。 - 要讓它們變成能運行的程序,得用
gcc
編譯,比如:
gcc a.c b.c main.c -o myprogram
這看起來簡單,但如果項目變大呢?
-
假設有 100 個源文件,每次都手動敲這串命令,累不說,還容易輸錯;
-
如果只改了
a.c
,手動編譯時還得重新編譯所有文件,浪費時間; -
不同文件有依賴關系(比如
main.c
要用a.c
的結果),手動編譯得記清順序,錯一步就失敗。
2. 為了解決麻煩,才有了自動化工具
就像做復雜的菜時,你需要一份「步驟清單」(先切菜、再炒肉、最后燉),再找個「幫手」按清單一步步做。
在編程里,「步驟清單」就是 Makefile
,「幫手」就是 make
。
3. 什么是 Makefile ?
Makefile
是一個我們自己創建的文件(名字就叫 Makefile
,沒有后綴),里面寫的是「編譯規則」。
比如在一個 Makefile 里,你可以在里面寫下:
現在看一下代碼,后面會詳細講
# 規則1:最終要生成的程序叫 myprogram,它依賴 a.o、b.o、main.o
myprogram: a.o b.o main.ogcc a.o b.o main.o -o myprogram # 生成 myprogram 的命令# 規則2:a.o 依賴 a.c
a.o: a.cgcc -c a.c # 把 a.c 編譯成 a.o(中間文件)# 規則3:b.o 依賴 b.c
b.o: b.cgcc -c b.c# 規則4:main.o 依賴 main.c
main.o: main.cgcc -c main.c
簡單說,Makefile
就像一份「菜譜」:
- 明確最終要做什么(比如
myprogram
這個程序); - 明確需要哪些「原材料」(比如
a.o
這些中間文件); - 明確每一步怎么做(比如用什么命令編譯,先編譯哪個、后編譯哪個)。
4. 什么是 make ?
make
是 Linux 自帶的一個命令工具(就像 ls
、cd
一樣,輸入 make
就能運行)。
- 它的作用很單純:讀
Makefile
里的規則,然后自動執行命令。
比如剛才寫好了 Makefile
,你在終端敲一句 make
,它就會:
- 先看最終要生成
myprogram
,發現需要a.o
、b.o
、main.o
; - 檢查這些
.o
文件有沒有,如果沒有,就按規則編譯a.c
生成a.o
,以此類推; - 最后把所有
.o
文件拼起來,生成myprogram
。
如果之后我們只改了 a.c
,再敲 make
時,它會聰明地只重新編譯 a.o
和 myprogram
,其他沒改的文件不碰——省時間!
二、如何使用 make/Makefile
1. 如何創建第一個Makefile?
(1) 創建源文件
首先,創建一個簡單的C語言程序code.c
:
// code.c
#include <stdio.h>
int main() {printf("Hello, Makefile!\n");return 0;
}
(2) 創建Makefile文件
在相同目錄下創建Makefile
文件(注意大小寫和文件名):
touch Makefile
vim Makefile
(3) 編寫Makefile規則
在Makefile
中寫入以下內容:
# 目標: 依賴文件
code: code.cgcc -o code code.c # 注意這行必須以Tab鍵開頭
(4) 執行make命令
在終端輸入make
,它會自動讀取Makefile
并執行編譯:
$ make
gcc -o code code.c
此時,當前目錄下會生成可執行文件code
,運行它:
$ ./code
2. 依賴關系與命令
(1) 依賴關系
在Makefile中,每行規則的基本格式是:
目標文件: 依賴文件列表命令1命令2...
- 目標文件:要生成的文件(如
code
) - 依賴文件:生成目標所需要的文件(如
code.c
) - 命令:生成目標的具體操作(如
gcc -o code code.c
)
(2) make的執行邏輯
當你執行make
時,它會:
- 檢查目標文件是否存在
- 如果不存在,或依賴文件比目標文件更新(即依賴文件被修改過)
- 則執行對應的命令來生成/更新目標文件
(3) 為什么需要依賴關系?
假設你修改了code.c
,再次執行make
時:
$ make
make: 'code' is up to date.
make
會自動判斷:由于code
已存在且code.c
未修改,因此無需重新編譯——這就是Makefile
的智能編譯能力,大大節省時間!
3. 如何清理編譯結果?
(1) 添加clean目標
在Makefile
中新增一個clean
目標:
code: code.cgcc -o code code.c.PHONY: clean
clean:rm -f code # 刪除生成的可執行文件
(2) 執行清理命令
當需要刪除編譯結果時,執行:
$ make clean
rm -f code
(3) .PHONY 標簽的作用
.PHONY
用于聲明clean
是一個偽目標(即它不是真正的文件名),防止目錄中真的存在名為clean
的文件導致沖突。
4. Makefile的執行規則
(1) 默認執行第一個目標
當你直接輸入make
時,它會執行Makefile中的第一個目標(如上面的code
)。
(2) 如何執行其他目標?
通過指定目標名來執行特定規則,例如:
$ make clean # 只執行clean目標下的命令
$ make code # 只執行code目標下的命令(等同于直接make)
(3) 多個目標的執行順序
Makefile會按照依賴關系自動處理執行順序。例如:
all: program1 program2program1: file1.cgcc -o program1 file1.cprogram2: file2.cgcc -o program2 file2.c
執行make all
時,會先編譯program1
,再編譯program2
。
5. 常見錯誤與注意事項
(1) 命令行必須以Tab鍵開頭
在Makefile中,命令行必須以Tab鍵開頭,否則會報錯:
# 錯誤示例(使用空格縮進)
code: code.cgcc -o code code.c # 錯誤!會提示"*** missing separator. Stop."# 正確示例(使用Tab鍵縮進)
code: code.cgcc -o code code.c
(2) 文件名大小寫敏感
Makefile
和makefile
是不同的文件,GNU make默認優先讀取GNUmakefile
,然后是makefile
,最后是Makefile
。建議統一使用Makefile
。
三、偽目標是什么,為什么偽目標總被執行?
1. make如何判斷是否需要重新編譯?
當我們執行make
時,它會檢查兩件事:
- 目標文件(如
code
)是否存在 - 依賴文件(如
code.c
)的修改時間是否比目標文件更新
如果目標文件不存在,或依賴文件被修改過(修改時間比目標文件晚),make
就會執行命令重新生成目標文件。
舉個例子
# Makefile
code: code.cgcc -o code code.c
- 第一次執行
make
:生成code
文件 - 第二次執行
make
:make
發現code
已存在,且code.c
沒修改,==“code”已是最新 ==
$ make
gcc -o code code.c # 第一次執行,生成code
$ make
make: “code”已是最新
2. 什么是偽目標(.PHONY)?
(1)定義:
偽目標是用.PHONY
聲明的目標,它不代表一個真實的文件,而是一個動作名稱。
(2) 常見用途:
- 清理編譯結果(如
clean
目標) - 執行測試(如
test
目標) - 批量操作(如
all
目標)
示例:
.PHONY: clean # 聲明clean是偽目標
clean:rm -f code # 刪除生成的可執行文件
3. 為什么偽目標總是被執行?
(1)核心原因:
偽目標不對應真實文件,因此make
無法檢查它的修改時間。
當你執行make 偽目標名
時,make
會直接執行對應的命令,而不做任何檢查。
(2) 對比實驗:
情況1:普通目標(無.PHONY)
hello:echo "Hello, World!"
執行效果:
$ make hello
echo "Hello, World!"
Hello, World!
$ make hello
make: 'hello' is up to date. # 第二次不會執行,因為默認認為hello是文件且已存在
情況2:偽目標(有.PHONY)
.PHONY: hello
hello:echo "Hello, World!"
執行效果:
$ make hello
echo "Hello, World!"
Hello, World!
$ make hello
echo "Hello, World!" # 每次都會執行!因為hello是偽目標
Hello, World!
4. 為什么需要偽目標?
(1) 避免與文件沖突
如果目錄中真的有一個名為clean
的文件,會發生什么?
# 錯誤示例:沒有.PHONY的clean目標
clean:rm -f code
此時執行make clean
,make
會認為:“clean
文件已存在,無需執行任何命令”——這顯然不是你想要的!
(2) 強制執行命令
對于clean
、test
這類目標,你總是希望它們無條件執行,而不是根據文件時間判斷。
5. 常見偽目標示例
1. clean目標(最常見)
.PHONY: clean
clean:rm -f *.o # 刪除所有.o文件rm -f executable # 刪除可執行文件
2. all目標(批量編譯多個程序)
.PHONY: all
all: program1 program2 # 先編譯program1,再編譯program2program1: file1.cgcc -o program1 file1.cprogram2: file2.cgcc -o program2 file2.c
3. install目標(安裝程序到系統)
.PHONY: install
install:cp program /usr/bin/ # 復制程序到系統目錄
以上就是這篇博客的全部內容,下一篇我們將繼續探索Linux的更多精彩內容。
我的個人主頁
歡迎來閱讀我的其他文章
https://blog.csdn.net/2402_83322742?spm=1011.2415.3001.5343
我的Linux知識文章專欄
歡迎來閱讀指出不足
https://blog.csdn.net/2402_83322742/category_12879535.html?spm=1001.2014.3001.5482
非常感謝您的閱讀,喜歡的話記得三連哦 |