Makefile之自動生成依賴(8)

2021-08-25 11:10:57 字數 3110 閱讀 6747

makefile自動生成標頭檔案依賴是很常用的功能,本文的目的是想盡量詳細說明其中的原理和過程。

首先給出乙個本人在小專案中常用的makefile模板,支援自動生成標頭檔案依賴。

cc      = gcc 

cflags = -wall -o

includeflags =

ldflags =

objs = seq.o

targets = test_seq

.phony:all

all : $(targets)

test_seq:test_seq.o $(objs)

$(cc) -o $@ $^ $(ldflags)

%.o:%.c

$(cc) -o $@ -c $< $(cflags) $(includeflags)

%.d:%.c

@set -e; rm -f $@; $(cc) -mm $< $(includeflags) > $@.$$$$; \

sed 's,\($*\)\.o[ :]*,\1.o $@ : ,g' < $@.$$$$ > $@; \

rm -f $@.$$$$

-include $(objs:.o=.d)

.phony:clean

clean:

rm -f $(targets) *.o *.d *.d.*

讀入makefile

讀入被include的其它makefile

初始化makefile中的變數

推導隱晦規則,並分析所有規則

為所有目標建立依賴關係鏈

根據依賴關係,決定哪些目標需要重新生成

執行生成命令

從上面make的執行過程中可看出,要動態生成依賴關係,只能利用第2步讀入其它makefile的機制。那麼,我們是否可以先把生成的依賴關係儲存到檔案,然後再把該檔案的內容包含進來?

答案是yes! 只要利用include的機制。

include關鍵字是用於讀入其它makefile檔案。當該檔案不存在時,make會尋找是否有生成它的規則,如果有,則執行其生成命令,然後再嘗試讀入。在include前加減號"-"可以上make忽略其產生的錯誤,並不輸出任何錯誤資訊。

即是說,我們需要提供生成規則檔案的規則。例如,我們可以這樣動態生成標頭檔案依賴關係:

seq.d : seq.c

@echo 「seq.o seq.d : seq.c seq.h" > $@

-include seq.d

當make執行時,makefile中的內容將是這樣子(指記憶體上的資料):

seq.d : seq.c

@echo 「seq.o seq.d : seq.c seq.h" > $@

seq.o seq.d : seq.c seq.h

特別注意的是,由於對seq.c和seq.h的修改需要更新seq.d的內容(因為依賴關係可能已變化),因此seq.d也要在依賴關係的目標列表中。

基於上面的例子,現在可以開始討論如何自動生成標頭檔案依賴。

大多數c/c++編譯器提供了-m選項,可自動尋找原始檔依賴的標頭檔案,並生成依賴規則。對於gcc,需要使用-mm選項,否則它會把系統依賴的標頭檔案也包含進來。例如執行下面乙個命令:

gcc -mm seq.c
將輸出:

seq.o : seq.c seq.h
但我們需要結果是seq.d也要包含在目標列表中,所以還需要對它進行文字處理。因此,上面的例子可改為:

seq.d : seq.c

@set -e; \

gcc -mm $< > $@.$$$$; \

sed 's,\($*\)\.o[ :]*,\1.o $@ : ,g' < $@.$$$$ > $@; \

rm -f $@.$$$$

-include seq.d

第乙個命令@set -e。@關鍵字告訴make不輸出該行命令;set -e的作用是,當後面的命令的返回值非0時,立即退出。

那麼為什麼要把幾個命令寫在」同一行「(是對於make來說,因為\的作用就是連線行),並用分號隔開每個命令?因為在makefile這樣做才能使上乙個命令作用於下乙個命令。這裡是想要set -e作用於後面的命令。

第二個命令gcc -mm $< > $@.$$$$, 作用是根據原始檔生成依賴關係,並儲存到臨時檔案中。內建變數$<的值為第乙個依賴檔案(那seq.c),$$$$為字串"$$",由於makefile中所有的$字元都是特殊字元(即使在單引號之中!),要得到普通字元$,需要用$$來轉義; 而$$是shell的特殊變數,它的值為當前程序號;使用程序號為字尾的名稱建立臨時檔案,是shell程式設計常用做法,這樣可保證檔案唯一性。

第三個命令作用是將目標檔案加入依賴關係的目錄列表中,並儲存到目標檔案。關於正規表示式部分就不說了,唯一要注意的是內建變數$*$*的值為第乙個依賴檔案去掉字尾的名稱(這裡即是seq)。

第四個命令是將該臨時檔案刪除。

如果把內建變數都替換成其值後,實際內容是這樣子:

seq.d : seq.c

@set -e; \

gcc -mm seq.c > seq.d.$$$$; \

sed 's,\(seq\)\.o[ :]*,\1.o seq.d : ,g' < seq.d.$$$$ > seq.d; \

rm -f seq.d.$$$$

-include seq.d

最後,再把makefile的模式匹配應用上,就完成自動生成標頭檔案依賴功能了:

%.d : %.c

@set -e; \

gcc -mm $@ > $@.$$$$; \

sed 's,\($*\)\.o[ :]*,\1.o $@ : ,g' < $@.$$$$ > $@; \

rm -f $@.$$$$

-include seq.d

Makefile自動生成標頭檔案依賴

makefile自動生成標頭檔案依賴是很常用的功能,本文的目的是想盡量詳細說明其中的原理和過程。首先給出乙個本人在小專案中常用的makefile模板,支援自動生成標頭檔案依賴。cc gcc cflags wall o includeflags ldflags objs seq.o targets t...

Makefile自動生成標頭檔案依賴

makefile自動生成標頭檔案依賴是很常用的功能,本文的目的是想盡量詳細說明其中的原理和過程。首先給出乙個本人在小專案中常用的makefile模板,支援自動生成標頭檔案依賴。cc gcc cflags wall o includeflags ldflags objs seq.o targets t...

makefile自動產生依賴

makefile 中,可能需要書寫一些規則來描述乙個 o目標檔案和標頭檔案的依賴關係。例如,如果在 main.c 中使用 include defs.h 那麼我們可能需要如下那樣的乙個規則來描述當頭檔案 defs.h 被修改以後執行 make 目標 main.o 應該被重建。main.o defs.h...