此為牛客網Linux C++課程1.10&1.11&1.12 的課程筆記。
0. Makefile介紹
1. Makefile文件命名與規則
示例:
使用vim編寫如下名為Makefile的文件:
app:sub.o add.o mult.o div.o main.ogcc sub.o add.o mult.o div.o main.o -o appsub.o:sub.cgcc -c sub.c -o sub.oadd.o:add.cgcc -c add.c -o add.omult.o:mult.cgcc -c mult.c -o mult.odiv.o:div.cgcc -c div.c -o div.omain.o:main.cgcc -c main.c -o main.o
首先看第一行,app是我們的目標文件,冒號后面是生成該目標文件所需要的依賴,第二行是我們要執行的命令。
在使用sub.o add.o mult.o div.o main.o依賴時,發現目錄中沒有對應的.o文件,則向下尋找其他規則,執行以生成其依賴。注意,如果下面的規則中與第一行所需的依賴無關,則不會被執行,也就是說Makefile中的其他規則都是為第一條規則服務的。
2. 變量
有了變量我們寫makefile就方便一些,比如我們之前的makefile就可以如此改寫:
src = sub.o add.o mult.o div.o main.o
target = app$(target):$(src)$(CC) $^ -o $(target)sub.o:sub.cgcc -c sub.c -o sub.oadd.o:add.cgcc -c add.c -o add.omult.o:mult.cgcc -c mult.c -o mult.odiv.o:div.cgcc -c div.c -o div.omain.o:main.cgcc -c main.c -o main.o
把所有的依賴定義為src變量,把目標文件名定義為target變量,然后用 $ 取值,其中 $ (CC)是預定義變量,表示C編譯器名稱;$^ 也是預定義變量,表示所有的依賴文件。
3. 模式匹配
原先是按左邊的方式寫的,一個個寫很麻煩,這里可以使用模式匹配,即通配符%,在同一規則中,%匹配同一個字符串。
如此以來,之前的makefile可如此改寫:
src = sub.o add.o mult.o div.o main.o
target = app$(target):$(src)$(CC) $^ -o $(target)%.o:%.c$(CC) -c $< -o $@
src中的每一個依賴都可以匹配下面的這條規則。
4. 函數
現在通過模式匹配,避免了我們反復寫規則,但是依賴文件我們還是要一個一個寫在src里,有沒有辦法直接獲取這些文件的文件名呢?可以使用$(wildcard PATTERN…)函數。
舉例,當前目錄如下:
假如我們想讓在makefile文件中獲得當前目錄中所有.c文件的名稱,即可執行:
src = $ (wildcard ./*.c )
這樣就能獲得當前目錄下所有.c文件的名稱。
但是之前的示例代碼中需要的是與.c文件同名的.o文件,而目錄中沒有.o文件,我們可以使用$(patsubst < pattern>,< replacement>,< text>)函數:
我們現在想要在makefile中獲得與目錄中.c文件同名的.o文件,便調用patsubst函數把獲得的.c文件進行字符串替換即可.
該函數的作用簡而言之就是把< text >中的匹配< pattern >的串用< replacement >代替。
其中< text >字段由剛才調用的src = $ (wildcard ./*.c )獲得,然后我們想將其中所有的.c都替換成.o,可將原來的makefile文件修改如下:
src = $(wildcard ./*.c)
objs = $(patsubst %.c, %.o, $(src))
target = app$(target):$(objs)$(CC) $^ -o $(target)%.o:%.c$(CC) -c $< -o $@
可實現與最初的示例程序相同的功能。