make使用總結(7)-Makefile編寫
阿新 • • 發佈:2020-12-28
技術標籤:make使用總結標頭檔案發生變化make
make使用總結(7)-Makefile編寫
上篇文章編寫了最簡單的Makefile檔案。但它不夠完美。首先當.h
檔案發生變化時,需要先make clean
,再make
.這種方式在編譯大型專案時會變得很慢,因為它需要先刪除之前生成的所有中間檔案,再重新建立中間檔案。而理論上make只需要重新編譯此.h
檔案涉及到的相關原始檔。然後連結程式就可以了。這節就是要解決這個問題。
優化make時的標頭檔案依賴問題
例程原始碼連結:<>.
工程目錄如下:
其中,檔案common.c和main.c中引用了common.h檔案。
Makefile檔案如下:
# 檔案說明
# 所有的檔案都在同級目錄下。包括`.h`檔案,`.c`檔案,以及生成的`.o`檔案。
# 原始檔需要手動的新增到Makefile檔案中。
# 要生成的檔名
BIN := main
# 要編譯的原始檔
SRCS := main.c common.c
OBJS := $(SRCS:.c=.o)
DEPS := $(SRCS:.c=.d)
CC ?= gcc
INC_DIR ?= ./
WARNINGS ?= -Werror -Wall
CFLAGS ?= -O3 -g0 -I$(INC_DIR) $(WARNINGS)
LDFLAGS ?=
$(BIN):$(OBJS)
$(CC) -o [email protected] $^ $(LDFLAGS)
%.o:%.c
$(CC) $(CFLAGS) -c -o [email protected] $<
%.d: %.c
$(CC) -MM $(CFLAGS) $< | sed 's,\($*\)\.o[:]*,$(OBJPATH)/\1.o [email protected]:,g' > [email protected]
.PHONY:clean
clean:
rm -f *.o *.d $(BIN)
-include $(DEPS)
與之前的Makefile檔案不同之處有三點:
- 新添加了一個變數
DEPS
. - 新添加了一個規則
%.d: %.c
。 - 在檔案末尾引用了
-include $(DEPS)
.
我們現在的目標是當common.h檔案發生變化時,make應該重新生成common.o.而要達到這一目的,我們就需要修改common.o的依賴。如下的程式碼。這樣修改完成後,由於common.o
依賴於common.h
,所以當common.h
發生變化,make就會重新生成common.o
了。
common.o:common.c common.h
$(CC) $(CFLAGS) -c -o [email protected] $<
一般我們都是使用gcc
的-MM
選項自動化的實現這種依賴。如使用gcc -MM common.c
命令得到的輸出為common.o: common.c common.h
。
上面新新增的規則%.d: %.c
就是使用上面的方式實現自動化依賴的。下面詳細介紹這個規則
%.d: %.c
$(CC) -MM $(CFLAGS) $< | sed 's,\($*\)\.o[:]*,$(OBJPATH)/\1.o [email protected]:,g' > [email protected]
這個規則中的shell命令可以分為三部分:
$(CC) -MM $(CFLAGS) $<
.將它簡化並例項化後為gcc -MM common.c
.就是用來輸出common.o: common.c common.h
的內容資訊。然後將其資訊通過管道傳給sed命令。sed 's,\($*\)\.o[:]*,$(OBJPATH)/\1.o [email protected]:,g'
.這個sed命令作用是將內容common.o: common.c common.h
轉化成common.o common.d: common.c common.h
。即新增common.d
目標,讓它也依賴於common.c和common.h。為什麼要這樣做了?因為當common.c和common.h發生變化時,common.d檔案也要更新。- 關於sed命令的使用詳解
man sed
.
- 關於sed命令的使用詳解
> [email protected]
:將sed命令處理的結果common.o common.d: common.c common.h
重定向到檔案[email protected]
,即common.d檔案中。
有了這個規則後,make就可以為每個c檔案生成一個d檔案,用來存放此c檔案引用的標頭檔案資訊。最後使用-include $(DEPS)
將所有的d檔案載入到此Makefile.這樣我們的目就實現了。
關於技術交流
此處後的文字已經和題目內容無關,可以不看。
qq群:825695030
微信公眾號:嵌入式的日常
如果上面的文章對你有用,歡迎打賞、點贊、評論。