一、make 是啥?
make 是軟件構造工具,通過讀取 Makefile文件自動化完成構建。
二、make 核心?
target ... : prerequisites ...
? ? (TAB)command
1. target 名為目標文件,實際是Object File,或執行文件,以及標簽(Label)。
2. prerequisites 是target所依賴的文件或是目標。
如果 prerequisites 的修改時間比 target 更新,或者 target 文件不存在,command 被執行。首次執行 make 創建了 target 文件是因為 target 文件不存在,之后執行 make 會根據修改時間的屬性進行判斷,如更新了源碼內容,那么 command 還會再次執行。
這就是 Makefile 的規則和核心。
三、make 實例
標準的編譯過程:源文件先被編譯成目標文件,然后再由目標文件連接成可執行文件。
cc = gcc? ?
prom = calc? ?
deps = calc.h
obj = main.o getch.o getop.o stack.o?$(prom): $(obj)? ? ? ?
? ? $(cc) -o $(prom) $(obj)? ??main.o: main.c $(deps) ? ? ? ?
? ? $(cc) -c main.cgetch.o: getch.c $(deps)? ? ? ?
? ? $(cc) -c getch.cgetop.o: getop.c $(deps)? ? ? ?
? ? $(cc) -c getop.cstack.o: stack.c $(deps)? ? ? ?
? ? $(cc) -c stack.c
我們發現所有.c都會被編譯成相同名稱的.o文件,可以根據該特點再對其做進一步的簡化:
cc = gcc
prom = calc
deps = calc.h
obj = main.o getch.o getop.o stack.o$(prom): $(obj)
? ? $(cc) -o $(prom) $(obj)%.o: %.c $(deps)
? ? $(cc) -c $< -o $@
1. %.o:%.c,這是一個模式規則,表示所有的.o目標都依賴于與它同名的.c文件(當然還有deps中列出的頭文件)。
2. $< 是依賴關系表中的第一項(如果我們想引用的是整個關系表,那么就應該使用$^),具體到我們這里就是%.c。
3. $@ 是當前語句的目標,即%.o。這樣一來,make命令就會自動將所有的.c源文件編譯成同名的.o文件。不用我們一項一項去指定了。整個代碼自然簡潔了許多。
如果我們需要往工程中添加一個.c或.h,可能同時就要再手動為obj常量再添加一個.o文件,如果這列表很長,代碼會非常難看,為此,我們需要用到Makefile中的函數,再次簡化:
cc = gcc? ?
prom = calc? ?
deps = $(shell find ./ -name"*.h")? ?
src = $(shell find ./ -name"*.c")? ?
obj = $(src:%.c=%.o)? ??$(prom): $(obj)? ? ? ?
? ? $(cc) -o $(prom) $(obj)? ??%.o: %.c $(deps)? ? ? ?
? ? $(cc) -c $< -o $@? ??clean:? ? ? ?
? ? rm -rf $(obj) $(prom)
shell函數主要用于執行shell命令,具體到這里就是找出當前目錄下所有的.c和.h文件。而$(src:%.c=%.o)則是一個字符替換函數,它會將src所有的.c字串替換成.o,實際上就等于列出了所有.c文件要編譯的結果。
四、make 執行過程
man make:
... ...
-d? Print? debugging? information in addition to normal processing.? The debugging information says which files are being considered for remaking, which file-times are being compared and with what?results, which files actually need to be remade, which implicit rules are considered and which are applied---everything interesting about how make decides what to do.
基本信息輸出:make --debug=b
詳細信息輸出:make -d