在linux c/c++的開發過程中,當源**檔案較少時,我們可以手動使用gcc或g++進行編譯鏈結,但是當源**檔案較多且依賴變得複雜時,我們就需要一種簡單好用的工具來幫助我們管理。於是,make應運而生。
make主要用來管理c/c++專案,通過makefile書寫的規則來對專案中的源**檔案進行編譯,生成可執行的程式。
make執行的主要過程如下:當在shell中使用make命令時,make會尋找當前目錄下的makefile檔案,根據該檔案中的規則來確定依賴關係,如果乙個檔案所依賴的檔案比這個檔案要新,或者說修改時間更晚,那麼make會根據makefile中指明的命令來重新編譯生成該檔案。
另外,make除了自動尋找定義了編譯規則的makefile檔案外,還可以手動指明定義了規則的檔案。比如:
$ make -f rule.txt # rule.txt中為make規則
makefile由一系列的規則構成,一條規則的基本格式如下:
目標 : 條件
[tab] 命令
其中,需要在命令之前加乙個tab製表符,並且條件和命令都是可以省略的,但是只能省略其一,條件省略時一般做一些編譯以外的其他工作,當命令省略時其實也可以對目標進行編譯生成,這涉及到了makefile中的隱式規則,這裡不過多贅述,我們只討論顯式規則。
如make流程所述,當條件中的檔案比目標要新時,會執行tab後的命令。
makefile中有很多規則時,當在shell中執行make
命令,缺省會將第一條規則的目標作為最終生成的目標。
比如下面這個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
這個最終目標。
但是如果我們只想生成某個中間的目標也是可以的,比如只生成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的負擔。
參考:
幾種make工具的區別
cmake cmake是乙個跨平台的安裝 編譯 工具,可以用簡單的語句來描述所有平台的安裝 編譯過程 他能夠輸出各種各樣的makefile或者project檔案。cmake 並不直接建構出最終的軟體,而是產生標準的建構檔 如 unix 的 makefile 或 windows visual c 的p...
make命令與Makefile檔案簡介
make工程管理,就是管理工程專案中的幾個檔案。大家在平時的練習中,編譯的檔案個數一般不超過五個,即使有幾個檔案進行了更改,也只需要對其重新編譯即可。但是工程若由成百上千個檔案組成,而只有其中個別檔案進行了修改,如果此時不知道哪幾個檔案被更改了,就只能用gcc把所有的檔案重新編譯一遍,這樣大大降低了...
linux 下面make工具的使用
在vs下面的工程檔案,光使用gcc命令已經很麻煩了,這時候就要用make命令,就像是乙個工程一樣,在vs下面微軟給我們做好了各種方便的用法,但是在linux下面就要靠我們自己寫了。使用make就一定要有個makefile,它描述了軟體包中各個檔案之間的關係,提供了更新每個檔案的命令。在乙個軟體包裡,...