make工具簡介

在Linux C/C++的開發過程當中,當源代碼文件較少時,咱們能夠手動使用gcc或g++進行編譯連接,可是當源代碼文件較多且依賴變得複雜時,咱們就須要一種簡單好用的工具來幫助咱們管理。因而,make應運而生。html

make主要用來管理C/C++項目,經過Makefile書寫的規則來對項目中的源代碼文件進行編譯,生成可執行的程序。node

make流程

make執行的主要過程以下:當在shell中使用make命令時,make會尋找當前目錄下的Makefile文件,根據該文件中的規則來肯定依賴關係,若是一個文件所依賴的文件比這個文件要新,或者說修改時間更晚,那麼make會根據Makefile中指明的命令來從新編譯生成該文件。shell

另外,make除了自動尋找定義了編譯規則的Makefile文件外,還能夠手動指明定義了規則的文件。好比:工具

$ make -f rule.txt  # rule.txt中爲make規則

Makefile的寫法

規則

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的負擔。


參考:

相關文章
相關標籤/搜索