🏆本篇主題為:從入門到精通:Make與Makefile完全指南
🏆個人主頁:CILMY23-CSDN博客
🏆系列專欄:C++ | C語言 | Linux | Python | 數據結構和算法 | 算法專題
🏆感謝觀看,支持的可以給個一鍵三連,點贊收藏+評論。如果你覺得有幫助,還可以點點關注
文章目錄
- 從入門到精通:Make與Makefile完全指南
- 1. 什么是Make/Makefile?
- 為什么需要Make?
- 2. 安裝
- Centos安裝
- 3. Makefile基礎語法
- 基本結構
- 4. Makefile的特性
- 4.1 makefile的執行順序
- 4.2 makefile無法生成可執行文件
- 如何強制重新編譯?
- 4.3 makefile進行多文件編譯
- 4.4 makefile的自動推導
- 4.5 makefile的變量
- 4.6 makefile省去中間過程
從入門到精通:Make與Makefile完全指南
1. 什么是Make/Makefile?
Make是一個自動化構建工具,主要用于管理源代碼的編譯和構建過程。它通過讀取Makefile文件來執行構建任務,能夠自動檢測文件變化并僅編譯必要內容,顯著提升開發效率。
為什么需要Make?
-
自動化重復的編譯命令
-
處理復雜的依賴關系
-
實現增量編譯(僅編譯修改過的文件)
-
標準化團隊的構建流程
2. 安裝
Centos安裝
# CentOS/RHEL
sudo yum install make
3. Makefile基礎語法
因為make是一個命令,而makefile是一個文件,所以我們需要在我們的當前目錄下創建一個makefile文件。
基本結構
Makefile 規則的基本格式為:
makefile
目標(target): 依賴(dependencies)command
makefile主要分為三個部分
- 目標文件 (target):要生成的文件或操作名稱(如 hello.exe 或 clean)。
- 依賴文件 (dependencies):生成目標所需的文件或條件(如 hello.c)。
- 依賴方法,命令 (command):生成目標的具體命令(以 Tab 開頭,不能用空格)。
參考如下,這里的phony先忽略,我們先看前面的就行了。
根據上圖我們可以解釋一下這三個部分,首先hello.exe是我們的目標文件,冒號后跟著的是一個依賴文件列表,按照空格為分割符,可以有多個文件,也可以為空。
再接下來是依賴方法,一定要用tab符號開頭,然后寫指令。
然后我們可以用make命令運行這一部分
我們可以看到生成了目標文件hello.exe,執行的命令,也就是依賴方法,是我們的第二行。
那我們生成的時候總會有很多的臨時文件,怎么辦呢?
這時候makefile就提供了一個清理功能。
我們可以在makefile文件中編輯clean,實現這一功能。
我們在終端中輸入 make clean 就可以很好的清理了。
4. Makefile的特性
4.1 makefile的執行順序
我們利用make執行makefile的時候,默認是從上往下執行的,也就是會生成第一個目標文件。
make會根據我們的makefile自動執行編譯/清理工作。
4.2 makefile無法生成可執行文件
實際上makefile有一個特性,是對于最新的可執行文件默認不生成,這實際上是為了提高效率,你可以看到你的報錯如圖所示:
make說hello.exe 是最新的日期。
那makefile是怎么知道我們需要重新生成了呢?
這就不得不提我們之前涉及的一個時間了:
Make 的工作原理是基于時間戳的依賴檢查,Make 會對比目標文件(如 hello.exe)和依賴文件(如 hello.c)的修改時間:如果目標文件比依賴文件舊(或目標文件不存在),則執行命令重新生成。如果目標文件比依賴文件新,則跳過命令,提示 is up to date。
所以當我們第一次執行 make
gcc -o hello.exe hello.c
Make 檢測到 hello.exe 不存在 或 hello.c 被修改過,觸發編譯命令,生成 hello.exe。
第二次執行 make
make: 'hello.exe' is up to date.
Make 發現 hello.exe 已存在,且它的修改時間晚于 hello.c 的修改時間,因此認為無需重新編譯。
如何強制重新編譯?
如果希望無視時間戳強制重新編譯,可以使用.PHONY:
方法:
.PHONY:xxx
xxx對應的依賴方法總是要執行的,xxx對應的是目標文件,或者clean。
4.3 makefile進行多文件編譯
如果總是要寫每個文件那就很麻煩了,因為一個工程里可能有很多文件,所以makefile提供了一種方法直接進行多文件的編譯。
hello.exe:hello.cgcc -o $@ $^
這里的@
就對應我們的目標文件,^
就對應我們的依賴文件列表,這樣的話我們就可以進行多文件的編譯。
makefile就會自動替代,$可以理解為自動取內容。
4.4 makefile的自動推導
我們用makefile重新進行這個程序的完全翻譯過程就好做多了
我們發現makefile給我們都按照順序推導完了,生成了對應的目標文件,并且最終文件也可以運行.
從這個過程中我們發現,makefile/make會自動根據文件中的依賴關系,進行自動推導,幫助我們執行所有相關的依賴方法。
因為我們沒有hello.o的依賴文件的時候,是無法生成hello.exe可執行文件的,所以第二行的命令就無法執行,
1 hello.exe:hello.o2 gcc -o hello.exe hello.o
makefile就會去找對應的依賴
3 hello.o:hello.s
4 gcc -c hello.s -o hello.o
makefile也同樣找不到,直到最后一段找到了,然后此刻就會生成對應的依賴,所以這里有一個依賴鏈:修改hello.c會觸發后續所有目標的重建(hello.i → hello.s → hello.o → hello.exe)。這個過程就像入棧一樣,第一個入棧,然后第二個入棧……,執行的時候就像遞歸一樣,往回推導,這也就是我們的makefile會自動推導的情況。
如果makefile中的內容是亂序的,那makefile也會自動推導,也就是順序不影響makefile執行。但是我們得把最重要的文件放前面,就比如下面這種情況:
4.5 makefile的變量
makefile不像C語言那樣設計變量,它跟python一樣,左邊是變量名字,右邊的變量的內容。
目標文件的變量:
1 bin=hello.exe
//bin = hello.exe
注意,中間不能用空格, 也就是我們這里的第二種寫法是不允許的。
同樣的,依賴文件我們也可以采用這種形式
2 src=test.c
這里的依賴文件中間可以用空格隔開。
那如何使用變量呢?我們得加上$()
4.6 makefile省去中間過程
如果我們不想看到中間過程,只需要在對應的命令前面加上@就可以了。
這樣中間過程就很簡略了