[Linux] 簡單的 Makefile 使用 (% 萬用字元、$@ 特殊符號、.PHONY 假目標)
從 Windows 派轉來 Linux 平台的我,對於 Linux 常見的 Makefile 了解的很少,
後來學到的大概就只是知道怎麼寫簡單的規則,
不過看到別人 Makefile 裡寫的一堆 $@, $^, $< 的就都看不懂…
偶然看到別人分享的 GNU Make, Autotools, CMake 簡介 投影片,
對 Makefile 又開始有點興趣了,去借了 GNU Make 專案開發工具這本書來看,
雖然還只看到第二章,但已經覺得獲益匪淺,是本不錯的書呀~
下面是一個簡單的 Makefile 範例,主要目的是想要從 .cpp 編譯成 .o,從 .o 再連結成 test 這個執行檔:
.PHONY: all clean all: test test: *.o g++ -Wall -g -o $@ -ldl -Wl,-rpath='$$ORIGIN' $^ %.o: %.cpp g++ -Wall -g -c $^ clean: rm -rf test *.o
以 test: *.o 這一行來說,test 是所謂的工作目標 (target),冒號後面的 *.o 是必要條件 (prerequisite),
當必要條件裡任一個檔案的日期比工作目標要新的時候,就會執行它下面的指令,
(也就是 g++ 那一行或多行),這就是 Makefile 最基本的規則~
test: *.o g++ -Wall -g -o $@ -ldl -Wl,-rpath='$$ORIGIN' $^
對指令列來說,有一點很容易忘記的是它必須是用 tab 開頭的,用空白字元是不行的,
像我的 Sublime Text 預設是會將 tab 轉成空白字元,
但 Sublime Text 有個聰明的地方是當它發現檔名是 Makefile (或是 View > Syntax > Makefile) 時,
就不會自動將 tab 轉成空白字元,以免破壞了 Makefile 的格式~
以前我可能會每一個 .o 檔都寫一條相對應的規則,但現在就發現可以用 % 來代表一個萬用字元,
所以像是 make 在看到 %.o: %.cpp 這一行之後,
就會知道如果現在的工作目標是 a.o 的話,必要條件就得去找對應的 a.cpp,
就不用去寫一堆類似的規則了~
%.o: %.cpp g++ -Wall -g -c $^
另外也學到了可以使用一些 Makefile 裡的特殊符號,最常見的是:
– $@ 代表工作目標 (上例中的 %.o)
– $^ 代表所有的必要條件 (上例中的 %.cpp)
– $< 代表第一個必要條件 (上例中的 %.cpp,因為例子中只有一個必要條件)
另一個學到的是 .PHONY 這個看起來很怪異的工作目標…
像我們有定義 all 這個工作目標,但如果目錄裡真的有一個叫 all 的檔案的話,
make 會去比較 all 這個檔案與其必要條件的更新日期,來決定要不要更新 all…
但這並不符合我們的預期,我們想要的是 make all 的時候就是要去跑後面的東西,
這時可以用 .PHONY 將 all 宣告成一個假的工作目標,這樣 make 就不會去找 all 這個檔案了:
.PHONY: all clean
有學到更好用的 Makefile 語法後,再來繼續分享囉~^^
參考資料:How do I use g++ to create object file with a specific name