值得思考的問題:目標檔案.o是否只依賴於原始檔.c?編譯器是如何編譯原始檔和標頭檔案的?
解答:預處理器將標頭檔案的**直接插入原始檔,編譯器只通過預處理器的原始檔產生目標檔案。如果規則中以原始檔為依賴,命令可能無法執行。因為在修改**的時候有可能只改動了標頭檔案,原始檔沒有被修改。如果規則中只是以原始檔為依賴目標,makefile裡面某條規則的依賴並不比目標更新,因此命令不同執行,但其實目標所間接依賴的標頭檔案已經被修改,對應的命令應該被執行。這是編譯行為帶來的缺陷。
解決的方法之一:將所有的標頭檔案作為依賴出現於每個目標對應的規則中,這樣標頭檔案被改變之後可以執行規則中的命令。但是,這種方法有缺陷嗎?上面「所有的」三個字被加粗,這裡的解決方案並不好,雖然可以解決問題。因為當任意乙個標頭檔案改動,任何原始檔都將被重新編譯(編譯低效),當專案中標頭檔案數量巨大時,makefile將很難維護
於是有了下面瘋狂的想法:
(1)通過命令自動生成對頭檔案的依賴;
(2)將生成的依賴自動包含進makefile中;
(3)當頭檔案改動後,自動確認需要重新編譯的檔案。
(1)linux命令sed;
(2)編譯器依賴生成選項gcc -mm(gcc -m);
示例**:
test:
echo
"test=>abc+abc=abc" | sed 's:abc:xyz:g'
echo
"main.o : main.c func.h" | sed 's,\(.*\)\.o[ :]*,objs/\1.o : ,g'
echo
"/a/b/c/d/main.o : main.c func.h" | sed 's,\(.*\)\.o[ :]*,objs/\1.o : ,g'
echo
"/a/b/c/d/main.o : main.c func.h" | sed 's,\(.*\)\.o[ :]*,x/y/z/\1.o : ,g'
echo
"/a/b/c/d/main.o :::: main.c func.h" | sed 's,\(.*\)\.o[ :]*,x/y/z/\1.o : ,g'
# add prefix before .o
gcc -mm -e main.c | sed 's,\(.*\)\.o[ :]*,objs/\1.o : ,g'
gcc -m -e main.c | sed 's,\(.*\)\.o[ :]*,objs/\1.o : ,g'
(3)小技巧:如果乙個目標是有多個依賴的,那這多個依賴不需要一次性寫出來,可以根據需要拆分成多個。
例子:拆分目標的依賴(將目標的完成依賴拆分為多個部分依賴)
.phony : a b c
test : a b c
@echo "$^"
等價於
.phony : a b c
test : a b
test : b c
test :
@echo "$^"
有了原材料,如何將sed和gcc -mm用於makefile,並自動生成依賴關係?
直接開門見山:需要用到makefile裡的include。
參考:makefile中include的暗黑操作
12 自動生成依賴關係(中)
下面的 有沒有問題?phony all all mkdir test cd test mkdir subtest結果 在當前目錄中生成了 test 和 subtest兩個資料夾,和我們預期的不一樣 makefile 中命令的執行機制 示例改進 phony all all set e mkdir te...
Makefile自動生成標頭檔案依賴
makefile自動生成標頭檔案依賴是很常用的功能,本文的目的是想盡量詳細說明其中的原理和過程。首先給出乙個本人在小專案中常用的makefile模板,支援自動生成標頭檔案依賴。cc gcc cflags wall o includeflags ldflags objs seq.o targets t...
Makefile之自動生成依賴(8)
makefile自動生成標頭檔案依賴是很常用的功能,本文的目的是想盡量詳細說明其中的原理和過程。首先給出乙個本人在小專案中常用的makefile模板,支援自動生成標頭檔案依賴。cc gcc cflags wall o includeflags ldflags objs seq.o targets t...