一文入門(mén) Makefile

image

1、什么是 Makefile

一個(gè)企業(yè)級(jí)項(xiàng)目,通常會(huì)有很多源文件,有時(shí)也會(huì)按功能、類(lèi)型、模塊分門(mén)別類(lèi)的放在不同的目錄中,有時(shí)候也會(huì)在一個(gè)目錄里存放了多個(gè)程序的源代碼。

這時(shí),如何對(duì)這些代碼的編譯就成了個(gè)問(wèn)題。Makefile 就是為這個(gè)問(wèn)題而生的,它定義了一套規(guī)則,決定了哪些文件要先編譯,哪些文件后編譯,哪些文件要重新編譯。

整個(gè)工程通常只要一個(gè) make 命令就可以完成編譯、鏈接,甚至更復(fù)雜的功能。可以說(shuō),任何一個(gè) Linux 源程序都帶有一個(gè)Makefile 文件。

2、Makefile 的優(yōu)點(diǎn)

管理代碼的編譯,決定該編譯什么文件,編譯順序,以及是否需要重新編譯;

節(jié)省編譯時(shí)間。如果文件有更改,只需重新編譯此文件即可,無(wú)需重新編譯整個(gè)工程;

一勞永逸。Makefile 通常只需編寫(xiě)一次,后期就不用過(guò)多更改。

3、命名規(guī)則

一般來(lái)說(shuō)將 Makefile 命名為 Makefile 或 makefile 都可以,但很多源文件的名字是小寫(xiě)的,所以更多程序員采用的是 Makefile 的名字,因?yàn)檫@樣可以將 Makefile 居前顯示。

如果將 Makefile 命為其它名字,比如 Makefile_demo,也是允許的,但使用的時(shí)候應(yīng)該采用以下方式:

make -f Makefile_demo

4、基本規(guī)則

Makefile 的基本格式為:

目標(biāo): 依賴(lài)

(tab)規(guī)則

目標(biāo) --> 需要生成的目標(biāo)文件

依賴(lài) --> 生成該目標(biāo)所需的一些文件

規(guī)則 --> 由依賴(lài)文件生成目標(biāo)文件的手段

tab --> 每條規(guī)則必須以 tab 開(kāi)頭,使用空格不行

例如我們經(jīng)常寫(xiě)的 gcc test.c -o test,使用 Makefile 可以寫(xiě)成:

test: test.c

gcc test.c -o test

其中,第一行中的 test 就是要生成的目標(biāo),test.c 就是依賴(lài),第二行就是由 test.c 生成 test 的規(guī)則。

Makefile 中有時(shí)會(huì)有多個(gè)目標(biāo),但 Makefile 會(huì)將第一個(gè)目標(biāo)定為終極目標(biāo)。

5、工作原理

目標(biāo)的生成

檢查規(guī)則中的依賴(lài)文件是否存在;

若依賴(lài)文件不存在,則尋找是否有規(guī)則用來(lái)生成該依賴(lài)文件。

image

比如上圖中,生成 calculator 的規(guī)則是 gcc main.o add.o sub.o mul.o div.o -o,Makefile 會(huì)先檢查 main.o、add.o、sub.o、 mul.o、 div.o 是否存在,如果不存在,就會(huì)再尋找是否有規(guī)則可以生成該依賴(lài)文件。

比如缺少了 main.o 這個(gè)依賴(lài),Makefile 就會(huì)在下面尋找是否有規(guī)則生成 main.o。當(dāng)它發(fā)現(xiàn) gcc main.c -o main.o這條規(guī)則可以生成 main.o 時(shí),它就利用此規(guī)則生成 main.o,然后再生成終極目標(biāo) calculator。

整個(gè)過(guò)程是向下尋找依賴(lài),再向上執(zhí)行命令,生成終極目標(biāo)。

目標(biāo)的更新

檢查目標(biāo)的所有依賴(lài),任何一個(gè)依賴(lài)有更新時(shí),就重新生成目標(biāo);

目標(biāo)文件比依賴(lài)文件時(shí)間晚,則需要更新。

image

比如,修改了 main.c,則 main.o 目標(biāo)會(huì)被重新編譯,當(dāng) main.o 更新時(shí),終極目標(biāo) calculator 也會(huì)被重新編譯。其它文件的更新也是類(lèi)推。

6、命令執(zhí)行

make:使用此命令即可按預(yù)定的規(guī)則生成目標(biāo)文件。 如果 Makefile 文件的名字不為 Makefile 或 makefile,則應(yīng)加上 -f 選項(xiàng),比如:

make -f Makefile_demo

make clean:清除編譯過(guò)程中產(chǎn)生的中間文件(.o文件)及最終目標(biāo)文件。

如果當(dāng)前目錄下存在名為 clean 的文件,則該命令不執(zhí)行。

解決辦法是偽目標(biāo)聲明:.PHONY:clean。

特殊符號(hào):

  • :表示此命令即使執(zhí)行出錯(cuò),也依然繼續(xù)執(zhí)行后續(xù)命令。如:-rm a.o build/

@:表示該命令只執(zhí)行,不回顯。一般規(guī)則執(zhí)行時(shí)會(huì)在終端打印出正在執(zhí)行的規(guī)則,而加上此符號(hào)后將只執(zhí)行命令,不回顯執(zhí)行的規(guī)則。如:@echo $(SOURCE)

7、普通變量

變量定義及賦值:

變量直接采用賦值的方法即可完成定義,如:

INCLUDE = ./include/

變量取值:

用括號(hào)括起來(lái)再加個(gè)美元符,如:

FOO = $(OBJ)

系統(tǒng)自帶變量:

通常都是大寫(xiě),比如 CC、PWD、CFLAG,等等。

有些有默認(rèn)值,有些沒(méi)有。比如常見(jiàn)的幾個(gè):

CPPFLAGS : 預(yù)處理器需要的選項(xiàng) 如:-I

CFLAGS:編譯的時(shí)候使用的參數(shù) –Wall –g -c

LDFLAGS :鏈接庫(kù)使用的選項(xiàng) –L -l

變量的默認(rèn)值可以修改,比如 CC 默認(rèn)值是 cc,但可以修改為 gcc:CC=gcc

8、自動(dòng)變量

常用自動(dòng)變量:

Makefile 提供了很多自動(dòng)變量,但常用的為以下三個(gè)。這些自動(dòng)變量只能在規(guī)則中的命令中使用,其它地方使用都不行。

$@ --> 規(guī)則中的目標(biāo)

$< --> 規(guī)則中的第一個(gè)依賴(lài)條件

$^ --> 規(guī)則中的所有依賴(lài)條件

例如:

app: main.c func1.c fun2.c ?gcc ^ - o@

其中:^ 表示 main.c func1.c fun2.c,< 表示 main.c,$@ 表示 app。

模式規(guī)則:

模式規(guī)則是在目標(biāo)及依賴(lài)條件中使用 % 來(lái)匹配對(duì)應(yīng)的文件,比如在目錄下有 main.c、func1.c、func2.c 三個(gè)文件,對(duì)這三個(gè)文件的編譯可以由一條規(guī)則完成:

%.o:%.c ? (CC) –c< -o $@

這條模式規(guī)則表示:

main.o 由 main.c 生成, ? func1.o 由 func1.c 生成, ? func2.o 由 func2.c 生成。

這就是模式規(guī)則的作用,可以一次匹配目錄下的所有文件。

9、函數(shù)

Makefile 也為我們提供了大量的函數(shù),同樣經(jīng)常使用到的函數(shù)為以下兩個(gè)。需要注意的是,Makefile 中所有的函數(shù)必須都有返回值。在以下的例子中,假如目錄下有 main.c、func1.c、func2.c 三個(gè)文件。

通配符:

用于查找指定目錄下指定類(lèi)型的文件,跟的參數(shù)就是目錄+文件類(lèi)型,比如:

src = $(wildcard ./src/*.c)

這句話(huà)表示:找到 ./src 目錄下所有后綴為 .c 的文件,并賦給變量 src。

命令執(zhí)行完成后,src 的值為:main.c func1.c fun2.c。

patsubst:

匹配替換,例如以下例子,用于從 src 目錄中找到所有 .c 結(jié)尾的文件,并將其替換為 .o 文件,并賦值給 obj。

obj = (patsubst %.c ,%.o ,(src))

命令執(zhí)行完成后,obj 的值為 main.o func1.o func2.o。

特別地,如果要把所有 .o 文件放在 obj 目錄下,可用以下方法:

obj = (patsubst ./src/%.c, ./obj/%.o,(src))

10、小結(jié)

Makefile 其實(shí)提供了非常非常多的功能,但本文所寫(xiě)的對(duì)于一般的企業(yè)應(yīng)用完全夠用了。特別對(duì)于初學(xué)者,學(xué)習(xí)一些基礎(chǔ)知識(shí)(如本文),再輔一些案例(如本系列的幾個(gè)案例),完全可以達(dá)到企業(yè)用人標(biāo)準(zhǔn)了。正所謂要抓住事物的主要矛盾,可以先把基礎(chǔ)知識(shí)吃透再去延伸 Makefile 的其它知識(shí)。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀(guān)點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 來(lái)自陳浩的一片老文,但絕對(duì)營(yíng)養(yǎng)。 示例工程:3 個(gè)頭文件*.h,和 8 個(gè) C 文件*.c。 初 編譯過(guò)程,源文件...
    周筱魯閱讀 4,784評(píng)論 0 17
  • makefile關(guān)系到整個(gè)工程的編譯規(guī)則,一個(gè)工程中的源文件不計(jì)其數(shù),按其類(lèi)型、功能、模塊分別放在若干的目錄當(dāng)中,...
    Joe_HUST閱讀 1,982評(píng)論 0 3
  • makefile 介紹 make命令執(zhí)行時(shí),需要一個(gè) makefile 文件,以告訴make命令如何去編譯和鏈接程...
    Stan_Z閱讀 1,729評(píng)論 2 15
  • 書(shū)寫(xiě)規(guī)則 規(guī)則包含兩個(gè)部分,一個(gè)是依賴(lài)關(guān)系,一個(gè)是生成目標(biāo)的方法。在Makefile中,規(guī)則的順序是很重要的,因?yàn)?..
    Stan_Z閱讀 1,706評(píng)論 0 6
  • 對(duì)于那些傷害你的人,你可曾后悔過(guò),恨不得從未遇見(jiàn)過(guò)?;蛟S離開(kāi)并不艱難,艱難的是離開(kāi)以后的日子里你要一個(gè)人度過(guò)...
    時(shí)嘉許閱讀 423評(píng)論 0 4

友情鏈接更多精彩內(nèi)容