makefile的隱式規則

2022-03-13 16:41:17 字數 2637 閱讀 5029

target :=exe

source_code =hello.c

objs = $(source_code:.c=.o)

$(target):$(objs)

gcc $^ -o $@

clean:

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

一上來直接展示乙份makefile**。

功能: 從功能角度來說,這份makefile**可以編譯出對應的目標檔案,並且順利執行。

思考: 這其實是乙份質量不合格的makefile**。請仔細觀察。 

。。。。 什麼 ?  你看著這個makefile卻一點都不覺得奇怪嗎?(好吧,難道你平時寫makefile都是這樣寫的?  )

下面我們通過實驗來講解。

做點簡單修改,還是上面這份makefile,只修改編譯器, 更換為交叉編譯器來試試,貼**:

target :=exe

source_code =hello.c

objs = $(source_code:.c=.o)

$(target):$(objs)

/usr/external-toolchain/bin/arm-linux-gnueabi-gcc $^ -o $@

clean:

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

功能:請問現在更換為交叉編譯器,還能編譯出正確的目標檔案嗎?  

編譯觀察:

令人吃驚的答案:編譯報錯!

解答: 

當前截圖make報錯顯示:不是有效格式的.o檔案。

這裡的玄機是makefile的乙個暗黑操作:隱式規則。

做一下簡單修改即可:使用預定義的cc 這會改變隱式規則的行為。修改為如下圖所示**:

target :=exe

cc := /usr/external-toolchain/bin/arm-linux-gnueabi-gcc

source_code =hello.c

objs = $(source_code:.c=.o)

$(target):$(objs)

$(cc) $^ -o $@

clean:

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

這樣就能順利編譯出目標檔案了。

雖然可以通過增加cc變數進行簡單修改,達到順利生成目標檔案的目的,但是這樣的makefile仍舊不被推薦使用,因為使用了有可能產生隱式規則行為的**

這裡通過使用cc變數能夠順利編譯出目標檔案, 本質還是使用了隱式規則,即makefile在執行make對應的規則內的命令時,發現卻沒有有效的彙編檔案:

於是通過預設的gcc編譯器嘗試將本地的xx.c檔案去編譯為xx.o檔案。

如果本地沒有xx.c檔案,有乙個xx.p或者xx.cpp檔案,make的這種隱式規則也會去將其編譯為彙編檔案。

如果xx.p和xx.cpp同時存在,是選擇xx.p還是xx.cpp,這由make的隱式規則決定。

上面是正面講解makefile隱式規則, 下面我側面證明一下makefile隱式規則的存在。 

還是使用這份**來分析。注意:我們使用的編譯器是交叉編譯器哦!

雖然make這個makefile時報錯,但還是生成了hello.o(我自己先寫乙個hello.c放在與makefile的同一路徑下), 我們來列印一下這個hello.o的部分二進位制:

完成了上面的步驟,我們直接手動使用gcc編譯出乙個彙編檔案: 

觀察總結:

我們這份makefile內根本就沒有出現使用gcc的**啊,我們使用的是交叉編譯器啊!,竟然出現了gcc編譯出來的彙編檔案! 這說明什麼?

這說明當前的這份makefile在make後發生了隱式規則的執行!

makefile的隱式規則是大型makefile工程應注意極力避免的,這很可能導致無法解決的bug!大家需要了解一下makefile的隱式規則,避免寫下的makefile出現隱式規則的行為

這也是本部落格最開頭的例子使用gcc沒暴露出問題的原因,換成交叉編譯器去嘗試後,就會發現問題所在。

總結:重點是要先生成有效的依賴。本例的最佳改進是再增加一條包含%.o:%.c 的規則去得到有效的彙編檔案。參考我之前的makefile部落格,那裡有正規的makefile的寫法。

makefile 隱式規則

phony all all a.txt all b.txt a.txt echo this is b.txt echo this is 複製 示例2 makefile 現同名命令 phony all all echo command 1 all echo command 2 all echo thi...

Make的隱式規則

隱式規則1 當依賴出現重名時,make將所有的依賴整合,形成最後的依賴。2 當目標中的命令出現重複時,make將發出警告,使用後來的命令執行結果來替換前面的命令執行結果,因此在makefile中使用include時應避免在include所包含的檔案中使用命令。隱式規則2 make會提供一些自定義的變...

筆記 隱式轉換規則

學習並背誦全文型別 undefined null string boolean number 值undefined null 所有字串 true false 所有數字 nan object的成員叫物件,包括array,function,math,date,json,regexp等除了原始值之外的所有...