makefile生成多個目標檔案的寫法(linux程式設計師必須掌握的程式編譯技能)

2020-10-09 11:00:31

小編讀完陳皓大神關於Makefile的部落格之後,對Makefile的使用有了更深入的理解,在此附上陳皓大神makefile部落格的連結:https://blog.csdn.net/haoel/article/details/2886。部落格中針對Makefile的介紹、編譯和連結原理、以及規則都做了詳細的介紹,因此小編在此僅歸納兩種常用的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寫法

舉例同上,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、$@     目標檔案的集合

三、常用的makefile檔案模板

在本例中,因為涉及到伺服器端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,可參照第二種方法的案例再稍加修改即可。

若有疑問,可在評論區留言!