小編讀完陳皓大神關於Makefile的部落格之後,對Makefile的使用有了更深入的理解,在此附上陳皓大神makefile部落格的連結:https://blog.csdn.net/haoel/article/details/2886。部落格中針對Makefile的介紹、編譯和連結原理、以及規則都做了詳細的介紹,因此小編在此僅歸納兩種常用的makefile檔案的寫法,希望可以幫助讀者掌握Makefile的寫法。(閱讀過程中若有不理解之處,可參考陳皓大神的部落格,以此來提升理解)
舉例:一個專案有1個標頭檔案(wrap.h),三個原始檔(server.c、client.c、wrap.c),要生成可執行目標檔案server、client,最簡單的寫法如下所示:
all:server client //目標檔案server和client
server:server.o wrap.o //server的依賴為server.o和wrap.o
gcc server.o wrap.o -o server -Wall //利用gcc編譯器生成可執行檔案server
client:client.o wrap.o //client的依賴為client.o和wrap.o
gcc client.o wrap.o -o client -Wall //利用gcc編譯器生成可執行檔案client
server.o:server.c wrap.h //server.o的依賴為server.c和wrap.h
gcc -c server.c -o server.o -Wall //利用gcc編譯器生成中間目標檔案server.o
client.o:client.c wrap.h //同上
gcc -c client.c -o client.o -Wall
wrap.o:wrap.c wrap.h //同上
gcc -c wrap.c -o wrap.o -Wall
在終端輸入命令make,執行makefile檔案可得到編譯結果如下:
我們可以看到編譯成功,成功生成了client.o、wrap.o、server.o等中間目標檔案以及client、server等可執行目標檔案,並且執行伺服器端和使用者端可以實現其功能,在此就不演示了。
該方法比較易懂,只需要依次對我們的.c檔案形成依賴關係,就可以根據目標檔案的需要生成對應的依賴目標,但是當一個專案比較大即有大量的.c檔案時,程式設計師需要編寫大量的依賴關係,工作量是非常大的,且容易遺漏出錯,因此需要掌握下面的方法
舉例同上,makefile檔案為:
target1=server //伺服器執行目標檔案server
target2=client //使用者端目標檔案client
src=$(wildcard *.c) //用wildcard函數找到所有.c檔案,server.c、client.c、wrap.c
deps=$(wildcard *.h) //用wildcard函數找到所有的.h檔案,wrap.h
obj=$(patsubst %.c,%.o,$(src)) //用patsubst函數將所有.c檔案替換成.o檔案
all:$(target1) $(target2) //目標檔案server和client,多個目標檔案一定形成此依賴關係
$(target1):server.o wrap.o //server的依賴為server.o和wrap.o
gcc $^ -o $@ -Wall //利用gcc編譯器生成可執行檔案server
$(target2):client.o wrap.o //client的依賴為client.o和wrap.o
gcc $^ -o $@ -Wall //利用gcc編譯器生成可執行檔案client
%.o:%.c $(deps) //任意一個.o中間目標檔案的依賴是其對應的.c檔案,如:client.o的依賴為client.c
gcc -c $< -o $@ -Wall //根據目標檔案編譯的需求依次將依賴編譯成對應的中間目標檔案
.PHONY:clean //偽檔案,需要在終端輸入make clean才會呼叫
clean:
-rm -rf $(target1) $(target2) $(obj) //刪除所有的目標檔案以及中間目標檔案,用於重新編譯。
在終端輸入命令make,執行makefile檔案可得到編譯結果如下:
我們可以看到編譯結果與第一種方法是一樣的,但是依賴關係的表示卻十分簡單,即使有幾百個依賴關係也同樣適用,所以這種寫法對大型專案的開發是非常有好處的
常用的三個自動變數含義:
1、$< 第一個依賴檔案,若有多個目標檔案,依次編譯依賴檔案
2、$^ 所有依賴檔案的集合
3、$@ 目標檔案的集合
在本例中,因為涉及到伺服器端server和使用者端client有多個目標檔案,但是常規專案中往往只有一個目標檔案,這樣makefile的寫法就更為簡單了,可套用以下模板:
target=main //想要生成的可執行檔名稱可自定義,此處為main
src=$(wildcard *.c)
deps=$(wildcard *.h)
obj=$(patsubst %.c,%.o,$(src))
$(target):$(obj)
gcc $^ -o $@ -Wall
%.o:%.c $(deps)
gcc -c $< -o $@ -Wall
.PHONY:clean
clean:
-rm -rf $(target) $(obj)
常見的生成一個目標檔案的makefile,直接套用第三種方法的模板即可,
生成多個目標檔案的makefile,可參照第二種方法的案例再稍加修改即可。
若有疑問,可在評論區留言!