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...