介紹:
? ? ? ??make和Makefile是用于編譯和構建C/C++程序的工具和文件。Makefile是一個文本文件,其中包含了編譯和構建程序所需的規則和指令。它告訴make工具如何根據源代碼文件生成可執行文件,里面保存的是依賴關系和依賴方法。make是一個命令行工具,用于根據Makefile文件中定義的依賴關系和依賴方法來生成程序。
make/Makefile的使用:
? ? ? ? 在使用此構建工具時,首先,我們要建立一個名稱為 Makefile或makefile 文件,這里要注意 的是名稱是固定的,不可更改。建立之后就要進入vim編輯步驟,輸入依賴關系和依賴方法來對指定程序進行指令控制。
? ? ? ? 下面,我們使用最簡單的gcc編譯操作來對C語言源文件程序進行控制。
[zhu@zhujunhao ~]$ vim Makefile
[zhu@zhujunhao ~]$ cat Makefile
code.exe:code.c? ? ? ?#第一行叫做依賴關系,即對文件code.c進行操作
?? ?gcc code.c -o code.exe? ?#第二行叫做依賴方法,該方法對code.c文件進行編譯
[zhu@zhujunhao ~]$ make? #直接make,開始執行Makefile文件中指令
gcc code.c -o code.exe? ?#Makefile 的依賴方法操作
[zhu@zhujunhao ~]$ ll
total 24
-rw-rw-r-- 1 zhu zhu ?181 Dec ?7 09:15 code.c
-rwxrwxr-x 1 zhu zhu 8360 Dec ?7 17:02 code.exe? ?#make形成可執行文件code.exe
-rw-rw-r-- 1 zhu zhu ?827 Dec ?5 14:52 install.sh
-rw-rw-r-- 1 zhu zhu ? 40 Dec ?7 17:01 Makefile
? ? ??其中,依賴關系是所要針對的文件,上面依賴關系?code.exe:code.c 中的 mybin 叫做目標文件,make 操作的就是此文件,code.c?叫做依賴文件列表,兩者之間用 “ :?” 分割。依賴方法是要對此文件進行指令操作,上面的依賴方法?gcc code.c -o code.exe 是對code.c文件進行編譯處理。
? ? ? ? 這里要注意的是,當我們使用make后,就不能再次使用make對其進行編輯。這時我們需在Makefile文件中對相關東西進行清理工作。如下:
[zhu@zhujunhao ~]$ vim Makefile
[zhu@zhujunhao ~]$ cat Makefile
clear:? ? ? ? ? ? ? ? ? ? ? ? ? ?#定義clear的依賴關系
?? ?rm -f code.exe? ?? ? ?#clear對應的依賴方法
code.exe:code.c? ? ? ? #定義目標文件code.exe依賴關系
?? ?gcc code.c -o code.exe? ? ? ?#code.exe的依賴方法
[zhu@zhujunhao ~]$ make? ? ?#默認執行第一個依賴關系所對應的依賴方法。
rm -f code.exe
[zhu@zhujunhao ~]$ ll
total 12
-rw-rw-r-- 1 zhu zhu 181 Dec ?7 09:15 code.c
-rw-rw-r-- 1 zhu zhu 827 Dec ?5 14:52 install.sh
-rw-rw-r-- 1 zhu zhu ?65 Dec ?7 18:04 Makefile[zhu@zhujunhao ~]$ make code.exe? ? ?#進行說明執行第二個依賴關系所對應的依賴方法
gcc code.c -o code.exe
[zhu@zhujunhao ~]$ ll
total 24
-rw-rw-r-- 1 zhu zhu ?181 Dec ?7 09:15 code.c
-rwxrwxr-x 1 zhu zhu 8360 Dec ?7 18:05 code.exe
-rw-rw-r-- 1 zhu zhu ?827 Dec ?5 14:52 install.sh
-rw-rw-r-- 1 zhu zhu ? 65 Dec ?7 18:04 Makefile
? ? ? ? 這里需注意,Makefile 定義的依賴關系中的 “目標文件” 不一定非要是文件,主要作用在于依賴方法,比如上面的?clear?功能就是刪除文件操作。這里的 “目標文件” 是一個抽象的概念。
? ? ? ? Makefile和make 形成目標文件的時候,默認是從上到下掃描Makefile文件的,若不加以說明,默認形成的是第一個目標文件。
? ? ? ? 上面說到 make 只能編譯一次。但是我們發現,當修改源文件時,可再次進行 make 編輯,這是因為make會根據文件所對應時間的修改而再次進行編輯。使用 stat [文件或目錄] 可查看【文件或目錄i】所對應的詳細時間記錄。
[zhu@zhujunhao ~]$ stat code.c? ? ? ? ?#查看code.c文件所對應的時間記錄
? File: ‘code.c’
? Size: 181 ? ? ? ?? ?Blocks: 8 ? ? ? ? ?IO Block: 4096 ? regular file
Device: fd01h/64769d?? ?Inode: 1052177 ? ? Links: 1
Access: (0664/-rw-rw-r--) ?Uid: ( 1001/ ? ? zhu) ? Gid: ( 1001/ ? ? zhu)
Access: 2023-12-07 09:15:21.064989027 +0800
Modify: 2023-12-07 09:15:21.060988852 +0800
Change: 2023-12-07 09:15:21.060988852 +0800
?Birth: -
? ? ? ? 這里,所對應的時間為Access、Modify、Change三個記錄。其中,Access是最近一次對文件進行訪問(即讀文件)的時間,Modify是最近一次對文件內容進行修改的時間,Change是最近一次對文件屬性進行修改的時間。要注意的是Access所對應的文件訪問的時間不是每次訪問都會更新,在短時間內頻繁的訪問系統不會更新。這樣保證了不會對系統帶來太大的負擔。
文件時間:
? ? ? ? make編輯文件時查看文件所對應的時間查看的是Modify所對應的時間,也就是說只要Modify所對應的時間被修改,make即可再次進行編輯。這里,我們可使用 touch [文件] 指令,當不存在【文件】時將會創建文件,當存在【文件】時將會全部更新文件所對應的時間。
Makefile/makefile語法使用:? ? ? ?
1,.PHONY的使用
????????當我們不想改變文件所對應的時間時進行連續編譯,這時需要在Makefile/makefile文件中進行.PHONY修飾偽目標。
[zhu@zhujunhao ~]$ vim Makefile
[zhu@zhujunhao ~]$ cat Makefile
.PHONY:code.exe ? ?#修飾code.exe目標文件,成為一個偽目標,使其總是可以被執行
clean:? ? ? ? ? ? ? ? ? ? ? #我們也可用.PHONY修飾clean目標,即.PHONY:clean,使其總是執行
?? ?rm -f code.exe
code.exe:code.c ?
?? ?gcc code.c -o code.exe
[zhu@zhujunhao ~]$ make code.exe
gcc code.c -o code.exe
[zhu@zhujunhao ~]$ make code.exe
gcc code.c -o code.exe
[zhu@zhujunhao ~]$ make code.exe
gcc code.c -o code.exe
2,名稱的替換
????????在Makefile/makefile文件中可用 “ = ” 進行名稱替換工作,使用別名時只需用 $(別名) 進行替換即可,如下:
#使用 = 進行名稱的替換
? ?g=gcc
? ?o=-o
? ?c=code.c
? ?exe=code.exe#使用別名替換,即:$(別名)
? ?.PHONY:$(exe) ? ?#修飾code.exe目標文件,成為一個偽目標,使其總是可以被執行
? ?clean:
? ? ? ?rm -f $(exe)
? ?$(exe):$(c) ?
??? ? ?gcc $^ $(o) $@ ? # $@代表目標文件,$^代表依賴文件列表 ? ??
3,語法推導
? ? ? ? 在Makefile/makefile中,若存在多個依賴關系,當make運行其中一個依賴關系的依賴方法時,系統會先判斷依賴關系中對應的依賴文件列表,并且對應的依賴文件不存在時,將會自動往下繼續尋找,直到找到指定的命令來生成這個目標文件,若找不到,系統將會報出異常;若找到了,系統將會往上不斷返回執行對應的指令,以便生成這個目標文件。如下:
[zhu@zhujunhao ~]$ vim makefile
[zhu@zhujunhao ~]$ cat makefile
code.exe:code.o
?? ?gcc $^ -o $@
code.o:code.s
?? ?gcc -c $^ -o $@
code.s:code.i
?? ?gcc -S $^ -o $@
code.i:code.c
?? ?gcc -E $^ -o $@
以上的makefile的工作流程是這樣的:
- 首先,當你運行?
make code.exe
時,make會檢查?code.exe
是否已經存在。如果存在,make就不會重新編譯。如果不存在,make會找到它的依賴文件code.o
,若依賴文件code.o
不存在,系統將往下查找,運行指定的命令來生成這個目標文件。這個過程會一直繼續,直到所有的目標文件都被生成。 - 然后,對于每個目標文件,makefile都會檢查是否所有的依賴文件都已經被更新。如果是,那么目標文件就會被重新編譯。這個過程會一直繼續,直到所有的目標文件都被更新。?如果命令失敗了或全部指令運行完之后目標文件還沒有被更新,make會停止并顯示錯誤信息。
? ? ? ?總的來說,makefile定義了如何將C語言源代碼code.c編譯成可執行文件code.exe的過程。在編譯過程中,它首先將C語言源代碼預處理為中間文件code.i,然后將中間文件編譯為匯編文件code.s,接著將匯編文件code.s編譯成二進制文件code.o,最后將二進制文件鏈接為可執行文件code.exe。
[zhu@zhujunhao ~]$ make
gcc -E code.c -o code.i
gcc -S code.i -o code.s
gcc -c code.s -o code.o
gcc code.o -o code.exe
? ? ? ? 可看出,Makefile/makefile的程序指令運行中,依賴關系如同棧結構中不斷推導進棧,當查找到最終所以屬的目標文件時,依賴關系中對應的依賴方法將會不斷的出棧運行。這種形式就叫做makefile/Makefile的語法推到過程。
總:使用make和Makefile/makefile可以簡化編譯和構建程序的過程,只需要編寫一個簡單的Makefile/makefile文件,就可以自動化地編譯和鏈接程序。同時,Makefile/makefile還可以在不同的平臺上使用,使得程序的構建更加靈活和可移植。