makefile 可以自動推導生成 o規則

2021-07-28 20:58:22 字數 2887 閱讀 2804



cc      = gcc

cpp     = g++

rm      = rm -rf

## debug flag

dbg_enable   = 0

## source file path

src_path   := .

## target exec file name

target     := exe

## get all source files

srcs         += $(wildcard $(src_path)/*.cpp)

## all .o based on all .c

objs        := $(srcs:.cpp=.o)

## need libs, add at here

libs :=

## used headers  file path

include_path := ./

## used include librarys file path

library_path := /lib

## debug for debug info, when use gdb to debug

ifeq (1, $)

cflags += -d_debug -o0 -g -ddebug=1

endif

## get all include path

cflags  += $(foreach dir, $(include_path), -i$(dir))

## get all library path

ldflags += $(foreach lib, $(library_path), -l$(lib))

## get all librarys

ldflags += $(foreach lib, $(libs), -l$(lib))

build:$(objs)

# $(cpp) -c $(cflags) $(srcs)

$(cpp) $(cflags) -o $(target) $(objs) $(ldflags)

#可自動推導.o檔案生成規則 

sinclude $(srcs:.cpp=.d)

%d: %cpp

@echo "create depend"

$(cpp) -mm $(cflags) $< > $@.$$$$; \

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

$(rm) $@.$$$$

#$(objs):$(srcs)

# $(cpp) -c $(cflags) $(srcs)

clean:

$(rm) $(objs) $(target)

sinclude $(sources:.c=.d)

%d: %c

@echo "create depend"

$(cc) -mm $(cflags) $< > $@.$$$$; \

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

$(rm) $@.$$$$

sinclude $(sources:.c=.d) 這一行是非常關鍵的,它在當前makefile裡去include另外的makefile. 這裡「另外」的makefile是將sources變數裡所有.c替換成.d。 在我的例子裡就是dlist.d memory.d test.d debug.d. 意思就是執行到這裡

的時候先去依次執行dlist.d memory.d test.d debug.d. 這裡的.d檔案就是包含了每個.c檔案自動生成的對頭檔案的依賴關係。這個依賴關係將由下面的%d:%c來完成。

%d: %c

此規則的含義是:所有的.d檔案依賴於同名的.c檔案。

第一行;使用c編譯器自自動生成依賴檔案($<)的標頭檔案的依賴關係,並輸出成為乙個臨時檔案,「$$$$」表示當前程序號。如果$(cc)為gnu的c編譯工具,產生的依賴關係的規則中,依賴標頭檔案包括了所有的使用的系統標頭檔案和使用者定義的標頭檔案。如果需要生成的依賴描述檔案不包含系統標頭檔案,可使用「-mm」代替「-m」。

第二行;使用sed處理第二行已產生的那個臨時檔案並生成此規則的目標檔案。經過這一行後test.d裡內容如下:test.o: test.c aaron.h dlist.h debug.h 其他.d裡以此類推。

第三行;刪除臨時檔案。

到這裡基本的意義弄明白了,但是讓我不解的是%d: %c這個依賴的規則怎麼能被執行到的?按照我的理解makefile在執行時首先檢查終極目標main是否存在,如果不存在則建立(根據main的依賴規則),如果存在在需要檢視

main的依賴檔案是否存在並且是最新的,這我的例子裡就是要看test.o dlist.o memory.o debug.o是否存在且最新。這樣追下去是否沒有%d: %c什麼事啊, .d檔案也應該不存在或者說是空的。儘管我們include了.d檔案,但是沒有依賴規則去執行它啊。後來仔細閱讀了

makefile檔案的重建才明白了。

makefile如果由其它檔案重建(這裡我的makefile include了所有.d檔案,.d也可以看成是乙個makefile),makefile在讀入所有其他makefile檔案(.d)之後,首先將所讀取的每個makefile(.d)作為乙個目標,尋找更新它們的規則。同樣

如果此目標不存在則根據依賴規則重新建立。在例子裡其實.d檔案開始並不存在,所以當makefile在include這些.d檔案時首先看.d存在不,不存在就要去尋找.d的依賴檔案和規則。這裡就找到了%d: %c從而建立出真正的.d檔案。其實這裡的關鍵點就是對於

include了理解,它是把include的檔案首先當成乙個目標,然後要去尋找其依賴檔案和規則的,而不是我事先想象的簡單的把其他檔案的內容包含過來。

到此,問題解決,基本達到預期。

Makefile詳解 自動推導

gnu的make很強大,它可以自動推導檔案以及檔案依賴關係後面的命令,於是我們就沒必要去在每乙個 o 檔案後都寫上類似的命令,因為,我們的make會自動識別,並自己推導命令。只要make看到乙個 o 檔案,它就會自動的把 c 檔案加在依賴關係中,如果make找到乙個whatever.o,那麼what...

自動型別推導

c 03及之前的標準種,auto放在變數宣告之前,宣告變數為自動變數 還有一種為靜態變數 static變數 的儲存策略。但是這個關鍵字常省略不寫。c 11中,auto關鍵字放在變數之前,作用是在宣告變數的時候根據變數初始值的型別自動為此變數選擇匹配的型別。注意點 auto a1 10 正確 auto...

makefile自動變數

下面是所有的自動化變數及其說明 表示規則中的目標檔案集。在模式規則中,如果有多個目標,那麼,就是匹配於 目標中模式定義的集合。僅當目標是函式庫檔案中,表示規則中的目標成員名。例如,如果乙個目標是 foo.a bar.o 那麼,就是 bar.o 就是 foo.a 如果目標不是函式庫檔案 unix 下是...