📝前言:
這篇文章我們來講講Linux開發工具——make/makefile:
🎬個人簡介:努力學習ing
📋個人專欄:Linux
🎀CSDN主頁 愚潤求學
🌄其他專欄:C++學習筆記,C語言入門基礎,python入門基礎,C++刷題專欄
目錄
- 一,make/makefile基礎介紹
- make
- Makefile
- 二,具體示例
- 1. 基礎示例
- 1.1 時間戳
- 1.2 是否重新編譯判斷
- 2. 進階1——依賴鏈
- 3. 進階2——變量替換
- 4. 進階3——多文件
- 4.1 獲取當前目錄下的所有文件
- 執行的命令不回顯
- 4.2 %<
- 4.3 模式規則
一,make/makefile基礎介紹
make/Makefile
用于自動化構建和管理項目。
make
- 功能:make是一個命令工具,它根據
Makefile
中定義的規則來自動構建和管理項目。它可以自動檢測源文件的修改情況,并僅重新編譯那些需要更新的目標文件,從而大大提高了編譯效率。 - 工作原理:
make
通過讀取Makefile
中的規則,分析目標文件和依賴文件之間的關系(簡稱依賴關系)。然后,它根據文件的時間戳(modify
時間)來判斷哪些文件需要重新編譯。如果一個依賴文件的修改時間晚于目標文件,或者目標文件不存在,make
就會執行相應的命令來更新目標文件。 - 使用方法:在項目目錄中,只需在命令行中輸入
make
命令,它就會自動查找當前目錄下的Makefile
,并按照其中的規則進行構建。如果Makefile
中有多個目標,make
默認構建第一個規則,后面的要指定要構建的特定目標,例如make target_name
。
Makefile
- 作用:Makefile是一個文本文件,它包含了一系列規則,用于告訴
make
工具如何構建項目。它定義了項目中的目標文件、依賴文件以及構建目標所需的命令(方法)。 - 基本結構:
Makefile
由一系列規則組成,每個規則通常包含以下部分:- 目標:通常是要構建的文件,如可執行文件、目標文件或庫文件。也可以是一個抽象的目標,如
clean
用于清理生成的文件。 - 依賴:目標所依賴的文件列表。
- 命令:用于構建目標的命令。命令必須以
Tab
鍵開頭。
- 目標:通常是要構建的文件,如可執行文件、目標文件或庫文件。也可以是一個抽象的目標,如
(也可以認為:規則 = 依賴關系 + 依賴方法)
二,具體示例
1. 基礎示例
先對前面介紹到的基礎的概念和用法做演示。
步驟:
- 現在當前目錄下創建
Makefile
文件:touch ./Makefile
- 根據需求,編寫
Makefile
解釋:
code.exe
是目標文件,code.c
是源文件(這是一組依賴關系,code.exe
依賴code.c
)Tab
開頭,后面寫依賴方法(構造目標用的命令)- 一個抽象的目標
clean
,可以沒有所依賴的文件列表 - 依賴方法
調用示例:
make
默認調用第一個規則,即code.exe:code.c
這一個make clean
,調用clean
對應的規則- 為什么連續調用
make
會失敗呢?
因為:make
根據文件modify
的時間戳來判斷哪些文件需要重新編譯。
1.1 時間戳
那什么是modify
時間戳,?
stat
查看文件時間屬性
Access
:訪問時間,當文件被查看,如cat
的時候會被修改(但有一些系統會優化,即:多次查看后才修改,為了減少磁盤I/O操作)Modify
:修改時間,代表文件最后一次被修改的時間,即內容有所改動,Modify
就會改變Change
:變更時間,當文件屬性有變化的時候會改變Birth
:誕生時間,創建時的時間
1.2 是否重新編譯判斷
當源文件的modify
時間相比目標文件“舊”,代表沒有源文件沒有修改,則不重新編譯
當源文件的modify
時間相比目標文件“新”,代表源文件修改了,則重新編譯
如圖:我們在沒有執行make
之前,只有源文件1
,執行完后,有了目標文件1
,時間關系如上。此時再執行make
就不會再重新編譯
如果我們更改了源文件:
這時候,代表有新內容,目標文件就需要重新編譯
那有沒有辦法讓make
無視時間戳,讓依賴方法總是被執行呢?
有的兄弟,有的。那就是特殊目標聲明:.PHONY
,將目標標記為偽目標。
此時,make
不用去檢查偽目標對應的文件是否存在、是否更新,而是直接執行命令
2. 進階1——依賴鏈
依賴鏈的結構就像一個棧:
- 檢查其依賴
code.o
,發現code.o
不存在,則依賴方法入棧 - 檢查
code.o
的依賴code.s
,發現code.s
不存在,則依賴方法也入棧 - …
- 檢查
code.i
的依賴code.c
,發現code.c
存在,則執行code.i
的依賴方法 - 將棧中依賴方法依次執行
3. 進階2——變量替換
定義變量:
=
:遞歸展開變量(不會在定義變量時立即對右側的表達式進行求值,而是在使用該變量時才進行求值。這意味著變量的值可能會因為其他變量的改變而改變)
:=
:簡單展開變量(在定義變量時就對右側的表達式進行求值,變量的值在定義時就已經確定,后續不會因為其他變量的改變而改變)
引用變量:
$(變量名)
示例:
$@
和 $^
:
$@
指代目標文件,$^
指代依賴文件列表
即上面的內容可以改成:
這里$^
會自動對應這個方法的依賴關系中的$(SRC)
,$@
對應$(BIN)
4. 進階3——多文件
4.1 獲取當前目錄下的所有文件
在Makefile中執行命令:$(shell 命令)
使用函數:$(函數名 參數1,參數2…)
獲取當前目錄下所有.c
文件后綴的方法:
$(shell ls *.c)
,回顧:ls
這個命令只列出名稱$(wildcard *.c)
輸入
make
運行結果:
執行的命令不回顯
在命令前加:@
效果:
4.2 %<
當有多個源文件需要編譯成目標文件,且每個源文件的編譯命令基本相同時,使用 $<
能避免重復書寫源文件名稱。
$<
會被自動替換為當前規則中列出的第一個依賴文件的名稱。例如,對于規則 target: dep1 dep2 dep3
,在其對應的命令里使用 $<
,它就代表 dep1
4.3 模式規則
%
:通配符,如%.c
:所有以.c
結尾的文件
%.o: %.c
:這個規則中,%
所匹配的內容在目標和依賴中是相同的。(同名)
當 make工具處理這個規則時,會針對每個 .o
文件的構建分別執行一次規則里的命令
錯誤寫法:
報錯:
make: *** No targets. Stop.
因為:%.o: %.c
只是一個模式規則,并沒有具體構建目標。具體的構建目標是指在 Makefile 中明確指定要構建的文件,文件名需要是完整且能明確指向一個具體文件的。
正確使用示例:
額外語法:
- 命令可以多行,但是也要
Tab
開頭 - 注釋用
#
符號
理解執行過程:
- 具體構建目標:
code.exe
,依賴所有.o
文件,沒有.o
文件,于是到下一個規則%.o:%.c
%.o:%.c
規則中,make會針對每個.o
文件分別執行一次命令,此時,每個.o
文件變成了這個規則里的具體構建目標
運行結果:
🌈我的分享也就到此結束啦🌈
要是我的分享也能對你的學習起到幫助,那簡直是太酷啦!
若有不足,還請大家多多指正,我們一起學習交流!
📢公主,王子:點贊👍→收藏?→關注🔍
感謝大家的觀看和支持!祝大家都能得償所愿,天天開心!!!