[Linux] 簡單的 Makefile 使用 (% 萬用字元、$@ 特殊符號、.PHONY 假目標)

[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

 

(本頁面已被瀏覽過 12,887 次)

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *

這個網站採用 Akismet 服務減少垃圾留言。進一步了解 Akismet 如何處理網站訪客的留言資料