在Linux C/C++的開發過程當中,當源代碼文件較少時,咱們能夠手動使用gcc或g++進行編譯連接,可是當源代碼文件較多且依賴變得複雜時,咱們就須要一種簡單好用的工具來幫助咱們管理。因而,make應運而生。html
make主要用來管理C/C++項目,經過Makefile書寫的規則來對項目中的源代碼文件進行編譯,生成可執行的程序。node
make執行的主要過程以下:當在shell中使用make命令時,make會尋找當前目錄下的Makefile文件,根據該文件中的規則來肯定依賴關係,若是一個文件所依賴的文件比這個文件要新,或者說修改時間更晚,那麼make會根據Makefile中指明的命令來從新編譯生成該文件。shell
另外,make除了自動尋找定義了編譯規則的Makefile文件外,還能夠手動指明定義了規則的文件。好比:工具
$ make -f rule.txt # rule.txt中爲make規則
Makefile由一系列的規則構成,一條規則的基本格式以下:code
目標 : 條件 [tab] 命令
其中,須要在命令以前加一個Tab製表符,而且條件和命令都是能夠省略的,可是隻能省略其一,條件省略時通常作一些編譯之外的其餘工做,當命令省略時其實也能夠對目標進行編譯生成,這涉及到了Makefile中的隱式規則,這裏不過多贅述,咱們只討論顯式規則。htm
如make流程所述,當條件中的文件比目標要新時,會執行tab後的命令。ip
Makefile中有不少規則時,當在shell中執行make
命令,默認會將第一條規則的目標做爲最終生成的目標。ci
好比下面這個Makefile例子:開發
main: main.o sub.o gcc -o main main.o sub.o sub.o: sub.c sub.h gcc -c -o sub.o sub.c main.o: main.c sub.h gcc -c -o main.o main.c clean: rm sub.o main.o .PHONY: clean
當咱們在shell中執行make時,會最終生成main
這個最終目標。get
可是若是咱們只想生成某個中間的目標也是能夠的,好比只生成sub.o
,只須要採用make 最終目標
的形式就能夠了,即make sub.o
注意到示例中省略了條件的那條規則(目標爲clean的那條規則),正規上把它叫作僞目標,用來執行一些其餘的任務,如本例中清除編譯中生成的.o文件。固然,僞目標下的命令能夠是多種多樣的,好比將clean
下的命令改成ls
,當執行make clean
時,會列出當前目錄下的全部文件。可是有一點須要注意的是,若是咱們的目錄下已經有了一個叫作clean的文件,當咱們執行make clean
時,make就分不清這個clean究竟是那個了,爲了不這種狀況,須要用.PHONY: 僞目標1,僞目標2..
的方式來顯式的聲明僞目標。
當咱們Makefile中的規則變得很是多時,爲了方便,也爲了可維護性,咱們通常使用變量來代替某些信息。
Makefile中定義變量的格式以下:
變量名 := 變量值
其中:=
也該以使用=
,依我的喜愛。用$(變量名)
的形式來使用變量。
先前示例中即可精簡以下:
CC := gcc LD := gcc CFLAGS := -c OBJS := main.o \ sub.o main: $(OBJS) $(LD) -o main $(OBJS) sub.o: sub.c sub.h $(CC) $(CFLAGS) -o sub.o sub.c main.o: main.c sub.h $(CC) $(CFLAGS) -o main.o main.c clean: rm $(OBJS) .PHONY: clean
Tip: 有時候咱們的規則可能太長,寫在一行又很差看,可使用
\
來進行換行。
Makefile中還提供了一些內置變量,好比$(CC)
表明默認的C編譯器,$(CXX)
表明默認的C++編譯器。更多內置變量請參考這裏
Makefile中還提供了一些特殊的變量,不用定義且會根據所在的規則而改變,減小一些目標文件名和條件文件名的輸入。如下是六個經常使用的自動變量:
變量名 | 做用 |
---|---|
$@ |
目標的文件名 |
$< |
第一個條件的文件名 |
$? |
時間戳在目標以後的全部條件,並以空格隔開這些條件 |
$^ |
全部條件的文件名,並以空格隔開,且排除了重複的條件 |
$+ |
與$^ 相似,只是沒有排除重複條件 |
$* |
目標的主文件名,不包含擴展名 |
根據以上自動變量,咱們能夠將上面的示例改爲更簡便的形式:
CC := gcc LD := gcc CFLAGS := -c OBJS := main.o \ sub.o main: $(OBJS) $(LD) -o $@ $^ sub.o: sub.c sub.h $(CC) $(CFLAGS) -o $@ $< main.o: main.c sub.h $(CC) $(CFLAGS) -o $@ $< clean: rm $(OBJS) .PHONY: clean
另外,儘管make工具經常用來管理C/C++項目,可是用來管理其餘項目也是能夠的,好比彙編項目,Pascal項目,甚至是node.js的項目,make就是一個工具,來幫咱們管理一些構建的規則,只要規則寫的得當,怎麼用就隨你了。
最後,make雖然能夠很好來管理項目了,可是仍是不夠方便。試想一下,當Makefile中的規則愈來愈多,又臭又長的時候,make就又顯得很難用了,這也就是爲何cmake誕生的緣由。經過編寫Cmakelist,來指導cmake生成各類Makefile文件和project文件,從而減輕管理Makefile的負擔。
參考: