认识Makefile文件(什么作用,格式怎样,如何工作)
以下內(nèi)容源于C語言中文網(wǎng)的學習與整理,非原創(chuàng),如有侵權(quán)請告知刪除。
參考博客:Make 命令教程 - 阮一峰的網(wǎng)絡日志
一、Makefile文件是什么
Makefile 文件描述了 Linux 系統(tǒng)下 C/C++ 工程文件的編譯規(guī)則,比如某些文件是否需要編譯、文件編譯的順序、文件間的依賴關(guān)系、文件是否需要重建等等。
它用來自動化編譯 C/C++ 項目。一旦寫編寫好 Makefile 文件,只需要一個 make 命令,整個工程就開始自動編譯,不再需要手動輸入一堆源文件與參數(shù),也不需要手動執(zhí)行 GCC 命令。
以 Linux 下的C語言開發(fā)為例。多文件編譯生成一個文件,編譯的命令如下所示:
gcc -o outfile name1.c name2.c ...outfile 是要生成的可執(zhí)行程序的名字,nameN.c 是源文件的名字。當源文件的數(shù)量不多時,可以選擇這樣的編譯方式,但如果源文件很多,會遇到下面問題。
(1)編譯的時候需要鏈接庫的的問題
拿C語言來說,編譯的時候 gcc 只會默認鏈接一些基本的C語言標準庫,很多源文件依賴的標準庫都需要我們手動鏈接。比如,下面列舉了一些需要我們手動鏈接的標準庫:
- name1.c 用到了數(shù)學計算庫 math 中的函數(shù),我們得手動添加參數(shù) -Im;
- name4.c 用到了小型數(shù)據(jù)庫 SQLite 中的函數(shù),我們得手動添加參數(shù) -lsqlite3;
- name5.c 使用到了線程,我們需要去手動添加參數(shù) -lpthread。
除了標準庫,還有其他文件需要鏈接第三方庫。這導致編譯命令非常長,而且可能會涉及到文件鏈接的順序問題,所以手動編譯會很麻煩。如果使用 Makefile 就不一樣了,它會徹底簡化編譯的操作。把要鏈接的庫文件放在 Makefile 中,制定相應的規(guī)則和對應的鏈接順序。這樣只需要執(zhí)行 make 命令,工程就會自動編譯。每次想要編譯工程的時候就執(zhí)行 make ,省略掉手動編譯中的參數(shù)選項和命令,非常方便。
(2)編譯大的工程會花費很長的時間
如果我們?nèi)プ鲰椖块_發(fā),免不了要去修改工程項目的源文件,每次修改后都要去重新編譯。一個大的工程項目可不止有幾個的源文件,里面的源文件個數(shù)可能有成百上千個,比如一個內(nèi)核或者是一個軟件的源碼包。要完巨量文件的編譯,消耗的時間很長。
Makefile 支持多線程并發(fā)操作,會極大的縮短我們的編譯時間。而且編譯整個工程的時候,make 命令只會編譯我們修改過的文件,沒有修改的文件不用重新編譯,這也縮短了編譯時間。
當然還可能遇到其他問題,比如:工程文件中的源文件的類型很多,需要選擇不同的編譯器;文件可能會分布在不同的目錄中,使用時需要調(diào)整路徑等等。這些問題都可以通過Makefile 來解決。
我們只需要完整地編寫一次Makefile文件,以后只要不增加或者是刪除工程中的文件,Makefile 基本上不用去修改。
Makefile這些特征為為我們提供了極大的便利,很大程度上提高編譯的效率。
二、Makefile文件的書寫規(guī)則
1、規(guī)則的格式說明
(1)Makefile 描述的是文件編譯的相關(guān)規(guī)則,它的規(guī)則主要是兩個部分組成:依賴的關(guān)系(目標與依賴)、執(zhí)行的命令。其結(jié)構(gòu)如下所示:
targets : prerequisitescommand #或者 targets : prerequisites; commandcommand- targets是規(guī)則的目標。可以是 Object File(一般稱它為中間文件),也可以是可執(zhí)行文件,還可以是一個標簽。
- prerequisites是依賴文件,是生成 targets 所需要的文件或者是目標。可以多個,也可以沒有。
- command是make時執(zhí)行的命令(任意的 shell 命令)。一條規(guī)則中可以有很多行的命令;每行命令可以有很多條命令,每行中的多條命令之間用分號隔開;每行命令后面不需要添加什么符號表示結(jié)束。
- 目標和依賴文件之間要使用冒號分隔開,命令的開始一定要使用Tab鍵。
(2)下面代碼實現(xiàn)的功能就是編譯 test.c 文件。其中 test 是目標文件, test.c 是依賴文件,重建目標文件需要執(zhí)行的命令是gcc -o test test.c。然后我們在 shell 中執(zhí)行 make 命令,程序就會自動執(zhí)行,得到最終的目標文件。這就是 Makefile 的基本語法與使用方法。
test:test.cgcc -o test test.c2、Makefile的內(nèi)容
一個完整的Makefile文件中包含以下內(nèi)容:規(guī)則、變量的定義、文件指示、注釋等內(nèi)容。
(1)規(guī)則。規(guī)則包括顯式規(guī)則、隱晦規(guī)則。顯式規(guī)則說明如何生成一個或多的的目標文件,由 Makefile 的書寫者明顯指出要生成的文件、依賴文件和生成命令。隱晦規(guī)則是指由于?make 命令有自動推導的功能,我們可以簡略地書寫 Makefile。
(2)變量的定義。在 Makefile 中定義的變量一般都是字符串,當 Makefile 被執(zhí)行時,其中的變量都會被擴展到相應的引用位置上。
(3)文件指示。文件指示包括三個部分,一個是在一個 Makefile 中引用另一個 Makefile,就像C語言中的 include 一樣;另一個是根據(jù)某些情況指定 Makefile 中的有效部分,就像C語言中的預編譯 #if?一樣;還有就是定義一個多行的命令。
(4)注釋。Makefile 中只有行注釋,和 UNIX 的 Shell 腳本一樣,其注釋是用“#”字符。如果要在Makefile中使用“#”字符,可以用反斜杠進行轉(zhuǎn)義,如“\#”。
三、Makefile的工作流程
當執(zhí)行 make 命令時,make 就會到當前文件下尋找將要執(zhí)行的編譯規(guī)則,即?Makefile 文件。
Makefile文件的文件名可以是GNUmakefile、makefile 和 Makefile,一般寫成Makefile。
make命令也是按照這個順序去尋找Makefile文件。如果文件不存在,則make 就會給我們報錯。
make:*** 沒有明確目標并且找不到 makefile。停止1、Makefile 的具體工作流程
通過例子來說明Makefile 的具體工作流程。Makefile文件內(nèi)容如下:
main:main.o test1.o test2.ogcc main.o test1.o test2.o -o main main.o:main.c test.hgcc -c main.c -o main.o test1.o:test1.c test.hgcc -c test1.c -o test1.o test2.o:test2.c test.hgcc -c test2.c -o test2.o在 shell 中執(zhí)行 make 命令時,make 執(zhí)行的是 Makefile 文件中的第一個規(guī)則,即Makefile 文件中從上到下第一次出現(xiàn)依賴關(guān)系的那個規(guī)則,此規(guī)則的目標稱之為“終極目標”。
在上述例子中,第一個規(guī)則就是目標 "main" 所在的規(guī)則。該規(guī)則描述了 目標"main" 的依賴關(guān)系,并定義了鏈接 ".o" 文件以生成目標 "main" 的命令。在執(zhí)行這個規(guī)則所定義的命令之前,首先處理目標 "main" 的依賴文件(即main.o、test1.o、test2.o這些文件)的更新規(guī)則。
對這些 ".o" 文件為目標的規(guī)則處理有下列三種情況:
(1)目標 ".o" 文件不存在,則使用其描述規(guī)則創(chuàng)建它。
(2)目標 ".o" 文件存在,但是它所依賴的 ".c" 文件和 ".h" 文件中的任何一個文件比它更(第四聲)新(在上一次 make 之后被修改),則根據(jù)規(guī)則重新編譯生成它。
(3)目標 ".o" 文件存在,目標 ".o" 文件比它的任何一個依賴文件更新(它的依賴文件在上一次 make 之后沒有被修改),則什么也不做。
通過上面的更新規(guī)則,我們可以了解到中間文件(即編譯時生成的 ".o" 文件)的作用,即檢查某個源文件是否進行過修改,判斷最終目標文件是否需要重建。我們執(zhí)行 make 命令時,只有那些修改過的源文件或者是不存在的目標文件才會進行重建,而那些沒有改變的文件不用重新編譯,這樣在很大程度上節(jié)省時間,提高編程效率。
2、清除工作目錄中的過程文件
中間文件會讓整個工程看起來很亂,因此在編寫 Makefile 文件時,一般會在末尾加上下面這樣的規(guī)則語句,來清理編譯時的中間文件和生成的最終目標文件,方便我們下次的使用。
.PHONY:clean clean:rm -rf *.o testPHONY中文意思是“虛假”,因此“.PHONY”表明clean是一個偽目標。clean不是具體的文件,不會與第一個目標文件產(chǎn)生任何關(guān)聯(lián),因此執(zhí)行 make 時不會執(zhí)行它下面的命令。
以前不了解Makefile時存在的疑惑:Makefile文件中那么多的目標,想要達成這些目標,在make的時候,是在后面一個個地添加目標嗎?還是說只要make第一個目標,就會順序地帶動其他目標?現(xiàn)在看來,默認情況下執(zhí)行的是第一個目標,其他目標如果是第一個目標的依賴文件,則會先處理其他目標,處理完之后才進行第一個目標的命令執(zhí)行。當然,我們也可以在make后面直接指定目標,比如這里的make clean。
總結(jié)
以上是生活随笔為你收集整理的认识Makefile文件(什么作用,格式怎样,如何工作)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 研发基于GUI的随机数据生成工具(V4.
- 下一篇: DSA算法实现数字签名--java实现