第一次寫Makefile就...放棄(誤)
太久沒寫Makefile,寫一篇廢文把複習過程記錄下來
目標
- obj 資料夾要保持 src 的結構
- 每個 source code 要編譯成獨立的 object 檔案
過程
實作之前
Makefile 基礎語法為:
1 | tagret: prerequires |
用樹的 Postorder Traversal 來理解就是,每個 target 都是 node,prerequires 則是要往下拜訪的 node,command 則是拜訪 child node 完之後要執行的動作,例如:
1 | all: compile |
執行 make
指令後,makefile 在沒有指定的情況下,預設從第一個 target 作展開。
all
底下還有compile
節點,往下拜訪compile
compile
底下沒有節點,執行compile
裡的 command。1
2gcc -c helloworld.c
gcc -c main.c底下的節點都拜訪並執行完 command 了,回到上一層節點
all
,執行 command1
gcc -o main main.o helloworld.o
輸出大概長這樣
1
2
3gcc -c helloworld.c
gcc -c main.c
gcc -o main main.o helloworld.o
其他語法
因為要展開整個專案底下的 source code,編譯階段如果是手動加入每個檔案不如直接寫腳本,還有寫死參數會造成日後維護困難,所以要用上其他語法
變數
指定編譯器,之後要替換可以不用一個一個改,也不用擔心漏改或改錯等問題
1
COMPILER := gcc
字串操作
列出 src 資料夾以下所有 *.c 檔案
執行
shell find
來尋找檔案1
2
3SRCDIR := src
SRCEXT := c
SOURCES := $(shell find $(SRCDIR) -type f -name *.$(SRCEXT))替換 *.c 檔案的路徑作為 *.o 檔案的路徑
將含 *.c 結尾的字串都轉換成 *.o 結尾
1
$(SOURCES:.$(SRCEXT)=.$(OBJEXT)
替換資料夾
語法為
$(patsubst pattern,replacement,text)
,將test
中符合pattern
的字串用replacement
取代。下列語法的意思是將$(SOURCES:.$(SRCEXT)=.$(OBJEXT)
內含src
的字串都替換成obj
1
2
3
4
5SRCDIR := src
BUILDDIR := obj
SRCEXT := c
OBJEXT := o
OBJECTS := $(patsubst $(SRCDIR)/%, $(BUILDDIR)/%, $(SOURCES:.$(SRCEXT)=.$(OBJEXT)))
整合
1 | #Compiler and Linker |