makefile是一種描述依賴關係的文件,它主要描述的是整個工程編譯規則, 同時也給工程的維護提供很大的方便. 這在大型工程中非常實用. 在寫好makefile之後,只需要在命令行輸入make命令, 工程就按照既定的makefile規則進行"自動化編譯".
1. 編譯(compile)和鏈接(link):
我們通常所說的編譯一般來說指的是編譯和鏈接這兩個過程的總稱.
不管是什麼類型的源文件(.c .cpp .pas .i...), 都需要先通過編譯器中的編譯單元生成目標文件(Object File), 它在Windows下是.obj文件, 在Linux下是.o文件, 這個過程叫作編譯.
然後編譯器的鏈接單元把這些生成的目標文件合成爲可執行文件, 這時鏈接單元只使用這些目標文件, 並不關心源代碼, 這個過程叫作鏈接.
在很多時候, 由於源文件的數目過於龐大, 編譯後生成的目標文件數目也就很多, 在鏈接過程中由於需要指出所有目標文件, 這就顯得很不方便, 於是我們可以把多個目標文件打個包.
在Windows下管這種文件叫庫文件(Library File), 擴展名爲.lib;
在Linux下這種文件叫Archive File, 擴展名爲.a.
可見.lib和.a都是編譯的產物而非鏈接的產物.
2. makefile:
我們首先看一個簡單的makefile:
- CC = g++
- OBJS = main.o base.o derive.o
- EXEC = test
- $(EXEC): $(OBJS)
- $(CC) -o $@ $^
- main.o: main.cpp base.h derive.h
- $(CC) -c $<
- base.o: base.cpp base.h
- $(CC) -c $<
- derive.o: derive.cpp derive.h base.h
- $(CC) -c $<
- clean:
- rm -rf $(EXEC) *.o
這裏需要說明幾個概念: 變量, 目標, 依賴.
變量: CC = g++, 這個CC就是一個在makefile裏定義的變量, 在定義後可以使用, 使用時是$(CC).
目標和依賴: main.o: main.cpp base.hderive.h, 這個":"(冒號)分開的兩邊中, 左邊就是目標, 右邊就是該目標的依賴, 而下一行的命令就是對應於這一對目標/依賴關係的.當需要實現這個目標時, 如果依賴中有更新, 就需要執行下面的命令.
比如, 當我們執行:
- make clean
就會執行對應目標"clean"下的命令, 因爲clean是沒有依賴的, 所以這個命令總被執行.
3. 隱含變量:
在這個makefile文件中, 可以看到諸如$^ $< $@這樣的東西, 這被我稱爲makefile的隱含變量.
$^: 指的是當前依賴中的所有對象.
$<: 指的是當前依賴中的第一個對象.
$@: 指的是當前目標.