Makefile之自动生成依赖(8)
Makefile自動生成頭文件依賴是很常用的功能,本文的目的是想盡量詳細說明其中的原理和過程。
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.*基礎知識
在進行下一步之前,首先需要了解make的執(zhí)行步驟:
如何動態(tài)生成依賴關系?
從上面make的執(zhí)行過程中可看出,要動態(tài)生成依賴關系,只能利用第2步讀入其它Makefile的機制。那么,我們是否可以先把生成的依賴關系保存到文件,然后再把該文件的內(nèi)容包含進來?
答案是Yes! 只要利用include的機制。
include關鍵字是用于讀入其它Makefile文件。當該文件不存在時,make會尋找是否有生成它的規(guī)則,如果有,則執(zhí)行其生成命令,然后再嘗試讀入。在include前加減號"-"可以上make忽略其產(chǎn)生的錯誤,并不輸出任何錯誤信息。
即是說,我們需要提供生成規(guī)則文件的規(guī)則。例如,我們可以這樣動態(tài)生成頭文件依賴關系:
seq.d : seq.c@echo “seq.o seq.d : seq.c seq.h" > $@-include seq.d當make執(zhí)行時,Makefile中的內(nèi)容將是這樣子(指內(nèi)存上的數(shù)據(jù)):
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的內(nèi)容(因為依賴關系可能已變化),因此seq.d也要在依賴關系的目標列表中。
自動生成頭文件依賴
基于上面的例子,現(xiàn)在可以開始討論如何自動生成頭文件依賴。
自動生成依賴關系
大多數(shù)c/c++編譯器提供了-M選項,可自動尋找源文件依賴的頭文件,并生成依賴規(guī)則。對于gcc,需要使用-MM選項,否則它會把系統(tǒng)依賴的頭文件也包含進來。例如執(zhí)行下面一個命令:
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生成規(guī)則中的執(zhí)行命令解釋
第一個命令@set -e。@關鍵字告訴make不輸出該行命令;set -e的作用是,當后面的命令的返回值非0時,立即退出。
那么為什么要把幾個命令寫在”同一行“(是對于make來說,因為\的作用就是連接行),并用分號隔開每個命令?因為在Makefile這樣做才能使上一個命令作用于下一個命令。這里是想要set -e作用于后面的命令。
第二個命令gcc -MM $< > $@.$$$$, 作用是根據(jù)源文件生成依賴關系,并保存到臨時文件中。內(nèi)建變量$<的值為第一個依賴文件(那seq.c),$$$$為字符串"$$",由于makefile中所有的$字符都是特殊字符(即使在單引號之中!),要得到普通字符$,需要用$$來轉(zhuǎn)義; 而$$是shell的特殊變量,它的值為當前進程號;使用進程號為后綴的名稱創(chuàng)建臨時文件,是shell編程常用做法,這樣可保證文件唯一性。
第三個命令作用是將目標文件加入依賴關系的目錄列表中,并保存到目標文件。關于正則表達式部分就不說了,唯一要注意的是內(nèi)建變量$*,$*的值為第一個依賴文件去掉后綴的名稱(這里即是seq)。
第四個命令是將該臨時文件刪除。
如果把內(nèi)建變量都替換成其值后,實際內(nèi)容是這樣子:
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.dMakefile的模式匹配
最后,再把Makefile的模式匹配應用上,就完成自動生成頭文件依賴功能了:
%.d : %.c@set -e; \gcc -MM $@ > $@.$$$$; \sed 's,\($*\)\.o[ :]*,\1.o $@ : ,g' < $@.$$$$ > $@; \rm -f $@.$$$$-include seq.d總結
以上是生活随笔為你收集整理的Makefile之自动生成依赖(8)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: GitHub 上最受欢迎的 5 大 Ja
- 下一篇: S5PV210的内存映射