要談的主題則是在 Makefile 中萬用字元跟泛用規則的應用, 可以讓整個 Makefile 盡量變得簡潔有力
並且一窺 Makefile 的內部推導邏輯
一堆 .o 一堆 rule
當使用 Makefile 一段時間後, 大致上會碰到的問題就是如果你有一堆 .c 要編譯成 .o 檔的話手刻一堆 xxx.c -> xxx.o 的 rule 會讓人挺困擾的, 尤其是通常都是 gcc xxx.c -c -o xxx.o 之類的
但如果你是個懶惰牌的好 Programmer 那麼你可能會嘗試寫一些萬用字元的 rule
於是你寫下了以下的 rule
*.o: *.c gcc -o *.o -c *.c嗚呼! Let's Make
然後你會發現如果有兩個 .c 以上的話就會發現:「幹!不能動」
gcc -o *.o -c *.c gcc: fatal error: cannot specify -o with -c, -S or -E with multiple files compilation terminated. make: *** [*.o] Error 4錯誤訊息跟我們抱怨如果指定 -o 加上 -c, -S 或 -E 的話就不能輸入多個檔案
現在假設你還沒有任何的 .o 擋在該資料夾並且有 a.c b.c 要編譯
shell 真實看到的指令變成這樣
gcc -o -c a.c b.c然後就引發剛才的錯誤了XD
救命 難道只能寫一堆 rule 了嗎?
萬用字元不能動的主要原因在於 Makefile 為了避免與 shell 使用的萬用字元 * 衝突而選擇了另一個並且 *.c 跟 *.o 的 * 的部份哪知道會不會一樣, 所以 Makefile 有自己的萬用字元系統
*.o: *.c gcc -o *.o -c *.c所以在 Makefile 中是使用 % 作為萬用字元, 因此第一直覺會下出類似下面的建置規則
%.o: %.c gcc -o %.o -c %.c敲入 Make 後發現建置規則是有抓到了, 但是建置指令並沒有將 % 替換程式適當的字串
gcc -o %.o -c %.c gcc: error: %.c: No such file or directory gcc: fatal error: no input files compilation terminated. make: *** [a.o] Error 4主要原因在於建置規則中不是用 % 來表達該萬用字元是用 $@ 及 $^
(當然還有一堆其它 $ 開頭的神奇變數, 不過常用的大概就這些)
Makefile 萬用字元使用方式 %, $@, $^
$@, $^這幾個符號各代表不同意義, 但直接先看範例再來解說吧
%.o: %.c gcc -o $@ -c $^其中 $@ 代表建置目標, 所以以要建置 a.o 來看的話 $@ 等於 a.o
接著 $^ 則代表相依目標, 建置 a.o 時會替換成 a.c
從此之後就只要寫一個 .c -> .o 的建置規則在加上一個 link 成執行檔的規則即可!
這些萬用規則也可以拿來作一些方便的應用, 例如有時候你會將 debug 版本跟一般版跟分開放置
則你寫兩個 rule 則可以建置出不同編譯參數且在不同資料夾生成
debug/%.o: %.c gcc -o $@ -c $^ -g release/%.o: %.c gcc -o $@ -c $^ -O2
小結
Makefile 會了萬用字元後, 建置規則就可以寫的簡潔又好看在加上 .c/.cpp 與 .h/.hpp 相依性自動建立就很完整了
預計會在弄一篇文章寫產生 .c/.cpp 與 .h/.hpp 相依性的:P
沒有留言:
張貼留言