target :=exe一上來直接展示乙份makefile**。source_code =hello.c
objs = $(source_code:.c=.o)
$(target):$(objs)
gcc $^ -o $@
clean:
$(rm) $(target) $(objs)
功能: 從功能角度來說,這份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等除了原始值之外的所有...