Linux系統程式設計(四)Makefile編寫
Linux系統程式設計(四)Makefile編寫
4.1 Makefile 檔案介紹
在Winows
下,一般使用Visual Studio
進行編譯除錯,而在 Linux
的 C++
工程中,編譯器一般使用 makefile
來編譯,如 Netbeans
編譯器。所以在 Linux
開發時,不可避免會對工程檔案的 Makefile
檔案進行修改,本文介紹 Makefile
Makefile
檔案。在大型工程中,檔案會根據其型別、實現功能、實現模組的不同放在不同的目錄中,
Makefile
檔案可以指定哪些檔案需要先編譯,也可執行 shell
命令。其優勢為 自動化編譯 ,使得整個工程自動編譯,提高開發效率。4.2 Makefile 命名與規則
Makefile
檔案一般命名為 makefile
或者 Makefile
。編寫規則如下
target ... : dependence ...
shell command
...
- 目標(target):編譯目標,最終要生成的檔案
- 依賴(dependence):所需要的依賴目標,生成目標所需的檔案或目標
- 命令(command):shell命令,通過執行命令對依賴操作生成目標(命令前必須有
tab
)
下面舉個栗子,編寫 Makefile
編譯運算庫工程。
準備工作:Linux系統程式設計(三)靜態庫與動態庫製作與使用 3.2 運算庫靜態庫例項
6個原始檔add.c
,sub.c
,mult.c
,div.c
,head.h
,main.c
開始編寫Makefile的 第一個版本, 檔案如下
app: main.c add.c sub.c mult.c div.c
gcc main.c add.c sub.c mult.c div.c -o app
執行 make
命令,make
會執行我們編寫好的 gcc
app
![編譯結果](https://img.796t.com/res/2020/12-10/16/a27af96d761df8d6a29f8c660cce1b7f.png)
4.3 Makefile 工作原理
下面簡單分析下 Makefile
檔案的工作原理,在編寫或者修改 Makefile
也能更清楚其編譯過程。
規則一:Makefile
執行時,首先會查詢依賴 是否存在,如果存在,則繼續執行命令。如果不存在,則向下檢查其他規則,檢視是否有其他規則來生成依賴,如果找到,則執行該規則中的命令。 如上面所寫的 Makefile
版本一,首先檢查.c
檔案是否存在,如果存在,則執行 gcc
命令。
下面在改寫下之前的Makefile
檔案,更清楚看出依賴關係。
app: main.o add.o sub.o mult.o div.o
gcc main.o add.o sub.o mult.o div.o -o app
sub.o: sub.c
gcc -c sub.c -o sub.o
add.o: add.c
gcc -c add.c -o add.o
mult.o: mult.c
gcc -c mult.c -o mult.o
div.o: div.c
gcc -c div.c -o div.o
main.o: main.c
gcc -c main.c -o main.o
使用make
來編譯檔案,得到 可執行檔案 app
規則二:Makefile
檔案會檢查更新。在執行依賴時,會比較目標與依賴檔案的時間。如果生成依賴的時間比目標檔案的時間晚,則需要重新生成目標。如果依賴的時間比目標早,則目標不需要更新,對應的規則不需要執行。
版本二與版本一相比,對於修改的檔案才進行重新編譯,減少編譯的時間。
4.4 Makefile 變數
Makefile
中變數分為兩種:自定義變數,預定義變數。可以通過 $[變數名]
獲取變數值。
- 自定義變數:
變數名 = 變數值
- 預定義變數:
Makefile
定義的變數,可以直接使用。- AR:歸檔維護程式的名稱,預設值為
ar
- CC:C編譯器的名稱,預設值為
cc
- CXX:
C++
編譯器的名稱,預設值為g++
[email protected]
:目標的完整名稱$<
:第一個依賴檔案的名稱$^
:所有依賴檔案
- AR:歸檔維護程式的名稱,預設值為
下面修改 Makefile
,使用變數來編譯工程。
src=main.o add.o sub.o mult.o div.o
target=app
$(target):$(src)
$(CC) $(src) -o $(target)
sub.o: sub.c
gcc -c sub.c -o sub.o
add.o: add.c
gcc -c add.c -o add.o
mult.o: mult.c
gcc -c mult.c -o mult.o
div.o: div.c
gcc -c div.c -o div.o
main.o: main.c
gcc -c main.c -o main.o
4.5 模式匹配
在 Makefile
中,使用模式匹配符%
進行匹配字串。修改Makefile
檔案得到版本三。
src=main.o add.o sub.o mult.o div.o
target=app
$(target):$(src)
$(CC) $(src) -o $(target)
%.o: %.c
$(CC) -c $< -o [email protected]
4.6 函式用法
下面介紹兩個常用的函式:
$(wildcard PATTERN ...)
- 功能:獲取指定目錄下的指定型別的檔案列表
- 引數:
PATTERN
:指多個或多個目錄下對應的某種型別的檔案,多個目錄用空格隔開
- 返回值:得到若干個檔案的檔案列表,檔名之間用空格間隔
$(wildcard *.c ./sub/*.c)
$(patsubst <pattern>, <replacement>, <text>)
- 功能:查詢
text
中單詞是否符合模式pattern
,如果匹配,以replacement
替換 - 引數:
<pattern>
:可以包含萬用字元%
,表示任意長度字串<replacement>
:當包含萬用字元%
時,代表<pattern>
中%
匹配的字元
- 返回值:函式返回被替換後的字串
使用萬用字元模式匹配修改Makefile
,如下
src=$(wildcard ./*.c)
objs=$(patsubst %.c, %.o, $(src))
target=app
$(target):$(objs)
$(CC) $(objs) -o $(target)
%.o: %.c
$(CC) -c $< -o [email protected]
編譯結果與上面的版本相同,如下所示
在 Makefile
中新增目標 clean
,刪除中間生成檔案
src=$(wildcard ./*.c)
objs=$(patsubst %.c, %.o, $(src))
target=app
$(target):$(objs)
$(CC) $(objs) -o $(target)
%.o: %.c
$(CC) -c $< -o [email protected]
clean:
rm -f $(objs)