# Makefile 學習筆記 ###### tags: `makefile` 這邊記錄我學習 makefile 的路線。網路上的 makefile 筆記我是覺得有點難發漏,所以這邊記錄一下,在看這篇筆記之前,你可以需要先熟悉 gcc 系列的操作,如果不知道怎麼使用 gcc 或是的 linux shell 指令的話,可以去找 jserv 或者是鳥哥會有更詳盡的說明。 預計的學習路線 ```mermaid flowchart LR c語言--> gcc --> makefile --> cmake ``` ## 開發環境 ```shell $ gcc --version gcc (Ubuntu 11.3.0-1ubuntu1~22.04) 11.3.0 $ lscpu Architecture: x86_64 CPU op-mode(s): 32-bit, 64-bit Address sizes: 39 bits physical, 48 bits virtual Byte Order: Little Endian CPU(s): 4 On-line CPU(s) list: 0-3 Vendor ID: GenuineIntel Model name: Intel(R) Core(TM) i3-10110U CPU @ 2.10GHz ``` ## Makefile 是什麼? 只要你設定正確,你只需要在 shell 打 `make` 他就會自動幫你把該編譯的做編譯,該更新的做更新。 ```shell make ``` ## 最簡單的 makefile 怎麼寫? ### 簡單的 makefile 例題 創一個資料夾放三個檔案 ``` . ├── main.c ├── myHello.c └── myHello.h ``` 三個檔案分別是`main.c` ```c #include <stdio.h> #include "myHello.h" int main(int argc, char const *argv[]) { myPrintf(); return 0; } ``` `myHello.h` ```c void myPrintf(void); ``` `myHello.c` ```c #include <stdio.h> #include "myHello.h" void myPrintf(void){ printf("Hello\n"); return; } ``` 基本上這個可以直接用 `gcc` 編譯,他會編譯兩個 .c 檔案,然後把他們 link 在一起使用。這個 `-I` 會讓 gcc 去尋找現在的資料夾 `.` 找有相依的檔案一起拿來編譯。 ```shell $ gcc -o main main.c myHello.c -I. $ ./main ``` 那我們要 make 幹嘛?當你有更多的 .c 檔案要寫的時候你就會覺得很煩躁了。那怎麼用 make 呢? ### makefile 格式 ```makefile fun: main.c myHello.c gcc -o yoyo main.c myHello.c -I. ``` - `fun` 是你的目標名字,也就是之後你可以在shell 打 `make fun` 這樣使用 - 用分號分開的後面是相依檔案,本例題的檔案是 `main.c` 跟 `myHello.c` - 下一行用 `tab` 開頭,放你想要執行的指令。 ### 如何使用make變數? 當我們編譯很多檔案的時候,編譯器應該都是用 `gcc`,他們相關的 flag 應該也是相似的,所以如果能使用變數的話應該就太好了。那我們會這樣用 ```makefile CC = gcc CFLAGS = -I. happy: main.o myHello.o $(CC) -o yoyo main.o myHello.o $(CFLAGS) ``` 你的 macro 叫什麼都可以,但是 `CC` 代表 c compiler 、`CFLAGS` 代表編譯器的選項,像是 `-I -g -Wall ` 之類的。 ### 改成 .o 有什麼差別? makefile會覺得 happy 這個目標需要 main.o 跟 myHello.o 這兩個檔案,有了這兩個檔案之後會再用幫你做出 yoyo 這個檔案。所以他的輸出會變成 ```shell $ make gcc -I. -c -o main.o main.c gcc -I. -c -o myHello.o myHello.c gcc -o yoyo main.o myHello.o -I. ``` 第 2 行跟第 3 行是 make 內建的模板幫你做出來的,相當於以下的寫法 ```makefile happy: main.o myHello.o $(CC) -o yoyo main.o myHello.o $(CFLAGS) main.o: main.c myHello.h $(CC) -c -o main.o main.c $(CFLAGS) myHello.o: myHello.c myHello.h $(CC) -c -o myHello.o myHello.c $(CFLAGS) ``` 有沒有發現有很多重複的地方?有重複的地方就該出現在一個健康的工程師,把這份 makefile 更精簡的寫出來 ### 使用萬用字元 `%` ```makefile %.o : %.c $(DEPS) $(CC) -c -o %.o %.c $(CFLAGS) ``` `%` 代表萬用字元,應該是跟 regex 的 `.` 是類似的意思。 `%.o` 會對應到 `abc.o` 或是 `123.o` 這樣 ### 使用自動化變數 `$@` 跟 `$<` - `$@` 工作目標檔名 - `$<` 第一個必要條件的檔名 - `$^` 所有必要條件的檔名,並以空格隔開這些檔名 (這份清單已移除重複的檔名) ```makefile %.o : %.c $(DEPS) $(CC) -c -o $@ $< $(CFLAGS) happy: main.o myHello.o $(CC) -o $@ $^ $(CFLAGS) ``` happy 就是工作目標, `$@` 就會是 `happy` 。 ## 參考連結 - [GNU Make 官方網站](https://www.gnu.org/software/make/manual/make.html) - [用範例學 makefile](https://makefiletutorial.com/#make-clean) - [Jserv 的 makefile 教學](https://hackmd.io/@sysprog/SySTMXPvl)
×
Sign in
Email
Password
Forgot password
or
By clicking below, you agree to our
terms of service
.
Sign in via Facebook
Sign in via Twitter
Sign in via GitHub
Sign in via Dropbox
Sign in with Wallet
Wallet (
)
Connect another wallet
New to HackMD?
Sign up