1. 程式人生 > 其它 >make使用總結(7)-Makefile編寫

make使用總結(7)-Makefile編寫

技術標籤: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檔案不同之處有三點:

  1. 新添加了一個變數DEPS.
  2. 新添加了一個規則%.d: %.c
  3. 在檔案末尾引用了-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命令可以分為三部分:

  1. $(CC) -MM $(CFLAGS) $<.將它簡化並例項化後為gcc -MM common.c.就是用來輸出common.o: common.c common.h的內容資訊。然後將其資訊通過管道傳給sed命令。
  2. 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檔案也要更新。
    1. 關於sed命令的使用詳解man sed.
  3. > [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
微信公眾號:嵌入式的日常
如果上面的文章對你有用,歡迎打賞、點贊、評論。二維碼