日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

Makefile总结

發(fā)布時間:2025/3/14 编程问答 30 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Makefile总结 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

?

gcc編譯流程

1、編寫C程序源代碼

????? 2、預(yù)處理 (加入文件到源文件 include,)

????? 3、編譯 (目標文件.o)

4、鏈接? (可執(zhí)行文件)???

gcc? 選項

-c
編譯、匯編到目標代碼(.o),不進行鏈接。如上圖所示。

?

-o outfile
輸出到指定的文件。

?

Makefile的內(nèi)容

Makefile里主要包含:

1、顯式規(guī)則。顯式規(guī)則說明了,如何生成一個或多個的目標文件。這是由Makefile的書寫者明顯指出,要生成的文件,文件的依賴文件,生成的命令。

2、隱晦規(guī)則。由于我們的make有自動推導的功能,所以隱晦的規(guī)則可以讓我們比較粗糙地簡略地書寫Makefile,這是由make所支持的。

3、變量的定義。在Makefile中我們要定義一系列的變量,變量一般都是字符串,這個有點像C語言中的宏,當Makefile被執(zhí)行時,其中的變量都會被擴展到相應(yīng)的引用位置上。

4、文件指示。其包括了三個部分,一個是在一個Makefile中引用另一個Makefile,就像C語言中的include一樣;另一個是指根據(jù)某些情況指定Makefile中的有效部分,就像C語言中的預(yù)編譯#if一樣;還有就是定義一個多行的命令

5、注釋。Makefile中只有行注釋,和UNIX的Shell腳本一樣,其注釋是用“#”字符,這個就像C/C++中的“//”一樣。(如果你要在你的Makefile中使用“#”字符,可以用反斜杠進行轉(zhuǎn)義,如:“\#”)

Makefile的文件名

大多數(shù)的make都支持“makefile”和“Makefile”這兩種默認文件名。

三、makefile如何知道自己該干嘛

一句話:從目標到依賴關(guān)系,從依賴關(guān)系到目標,再從目標到依賴關(guān)系。

四、引用其它的Makefile

include的語法是:

??? include <filename>

注意事項:filename可以是當前操作系統(tǒng)Shell的文件模式(可以包含路徑和通配符)

include前面可以有一些空字符,但是絕不能是[Tab]鍵開始。include和<filename>可以用一個或多個空格隔開。

如果文件都沒有指定絕對路徑或是相對路徑的話,make會在當前目錄下首先尋找,如果當前目錄下沒有找到,那么,make還會在下面的幾個目錄下找:

??? 1、如果make執(zhí)行時,有“-I”或“--include-dir”參數(shù),那么make就會在這個參數(shù)所指定的目錄下去尋找。

??? 2、如果目錄<prefix>/include(一般是:/usr/local/bin或/usr/include)存在的話,make也會去找。

五、環(huán)境變量 MAKEFILES

如果你的當前環(huán)境中定義了環(huán)境變量MAKEFILES,那么,make會把這個變量中的值做一個類似于include的動作。這個變量中的值是其它的Makefile,用空格分隔。只是,它和include不同的是,從這個環(huán)境變量中引入的Makefile的“目標”不會起作用,如果環(huán)境變量中定義的文件發(fā)現(xiàn)錯誤,make也會不理。

建議不要使用這個環(huán)境變量,因為只要這個變量一被定義,那么當你使用make時,所有的Makefile都會受到它的影響。這也提醒我們,也許有時候你的Makefile出現(xiàn)了怪事,那時候就可以看看當前環(huán)境中有沒有定義這個變量。如果是的話就只需要取消那些環(huán)境變量即可。

六、makefile的的工作過程總結(jié)

GNU的make工作時的執(zhí)行步驟如下:

??? 1、讀入所有的Makefile。

??? 2、讀入被include的其它Makefile。

??? 3、初始化文件中的變量。

??? 4、推導隱晦規(guī)則,并分析所有規(guī)則。

??? 5、為所有的目標文件創(chuàng)建依賴關(guān)系鏈。

??? 6、根據(jù)依賴關(guān)系,決定哪些目標要重新生成。

??? 7、執(zhí)行生成命令。

其中1-5為第一階段,6、7為第二階段。第一階段中,如果定義跌變量被使用,那么make會把它展開在使用的位置,如果定義出現(xiàn)在依賴關(guān)系之中,那么僅當這條依賴被決定需要使用了,變量才會在其內(nèi)部展開。

Makefile一般采用的結(jié)構(gòu)式從上而下,下層目標是用來讓上層目標保持在最新狀態(tài)。

?

簡單程序介紹:

一、一個makefile的實例

test:main.o
??????? gcc -o test main.o

main.o:main.c
??????? gcc -c main.c -o main.o

clean:
??????? @rm -vf main.o test

?

二、Makefile的書寫規(guī)則

1)如果這個工程沒有編譯過,那么我們的所有C文件都要編譯并被鏈接。

??? 2)如果這個工程的某幾個C文件被修改,那么我們只編譯被修改的C文件,并鏈接目標程序。

??? 3)如果這個工程的頭文件被改變了,那么我們需要編譯引用了這幾個頭文件的C文件,并鏈接目標程序。

規(guī)則包括兩部分,一個是依賴關(guān)系,一個是生成目標的方法。

在Makefile中,規(guī)則的順序是很重要的,Makefile中只應(yīng)該有一個最終目標,其它的目標都是被這個目標所連帶出來的,所以一定要讓make知道你的最終目標是什么。一般來說,定義在Makefile中的目標可能會有很多(至少有兩個目標),但是第一條規(guī)則中的目標將被確立為最終的目標。如果第一條規(guī)則中的目標有很多個,那么,第一個目標會成為最終的目標。整個make所完成的也就是這個目標。

三、規(guī)則舉例

??? foo.o : foo.c defs.h

??????????? gcc -c -g foo.c

這個規(guī)則告訴我們兩件事:

1、文件的依賴關(guān)系,foo.o依賴于foo.c和defs.h的文件,如果foo.c和defs.h的時間戳要比foo.o的要新,或是foo.o不存在,那么依賴關(guān)系發(fā)生。

??? 2、如果生成(或更新)foo.o文件。也就是那個gcc命令,其說明了,如何生成foo.o這個文件。(當然foo.c文件include了defs.h文件)

四、規(guī)則的語法

targets : prerequisites

??????? command

??????? ...

????? 或是這樣:

????? targets : prerequisites ; command

??????????? command

??????????? ...

Targets(即目標)多數(shù)情況下是文件名,以空格分開,可以使用通配符。目標基本上是一個文件,也可以是許多個文件。

注意:目標可以使用任何名稱,并不一定非得是真實的文件名。

command是命令行,如果其不與“target:prerequisites”在一行,那么,必須以[Tab鍵]開頭,如果和prerequisites在一行,那么可以用分號做為分隔。第二種寫法,目前見過的大多數(shù)都采用第一種。

prerequisites也就是目標所依賴的文件(或依賴目標)。如果其中的某個文件要比目標文件要新,那么,目標就被認為是“過時的”,被認為是需要重生成的。

注意:當冒號的右邊沒有指定依賴關(guān)系時會怎么樣——只有在目標代表的文件不存在時才會進行更新的動作。

如果命令太長(這涉及到代碼的規(guī)范化問題,即增進代碼的可讀性),你可以使用反斜框(‘\’)作為換行符。make對一行上有多少個字符沒有限制。規(guī)則告訴make兩件事,文件的依賴關(guān)系和如何成成目標文件。

五、在規(guī)則中使用通配符

如果我們想定義一系列比較類似的文件,即可使用通配符,當意欲創(chuàng)建適應(yīng)能力較強的makefile時,通配符就很有用了。make支持三個通配符:“*”,“?”和“[...]”。這是和Unix的B-Shell是相同的。波浪號(“~”)字符在文件名中也有比較特殊的用途。如果是“~/test”,這就表示當前用戶的$HOME目錄下的test目錄。通配符代替了一系列的文件,如“*.c”表示所以后綴為c的文件。一個需要我們注意的是,如果我們的文件名中有通配符,如:“*”,那么可以用轉(zhuǎn)義字符“\”,如“\*”來表示真實的“*”字符,而不是任意長度的字符串。
??? 一個例子:

clean:
????????????? rm?-f?*.o
????? 很常見的,這是操作系統(tǒng)Shell所支持的通配符。這是在命令中的通配符。
??? print:?*.c
????????????? lpr?-p?$?
????????????? touch?print
?????? 上面這個例子說明了通配符也可以在我們的規(guī)則中,目標print依賴于所有的[.c]文件。注意:其中的“$?”是一個自動化變量。
????? objects?=?*.o
??? 上面這個例子,表示了,通符同樣可以用在變量中。并不是說[*.o]會展開,不!objects的值就是“*.o”。Makefile中的變量其實就是C/C++中的宏。如果你要讓通配符在變量中展開,也就是讓objects的值是所有[.o]的文件名的集合,那么,你可以這樣:
??? objects?:=?$(wildcard?*.o)
??? 這種用法由關(guān)鍵字“wildcard”指出。

wildcard把 指定目錄 ./ 和 ./sub/ 下的所有后綴是c的文件全部展開。

六、文件搜尋

在一些大的工程中,有大量的源文件,我們通常的做法是把這許多的源文件分類,并存放在不同的目錄中。所以,當make需要去找尋文件的依賴關(guān)系時,你可以在文件前加上路徑,但最好的方法是把一個路徑告訴make,讓make自動去找。

方法一:

Makefile文件中的特殊變量“VPATH”就是完成這個功能的,如果沒有指明這個變量,make只會在當前的目錄中去找尋依賴文件和目標文件。

VPATH = src:../headers

上面的的定義指定兩個目錄,“src”和“../headers”,make會按照這個順序進行搜索。目錄之間由“冒號”分隔。(當然,當前目錄永遠是最高優(yōu)先搜索的地方)

方法二:

另一個設(shè)置文件搜索路徑的方法是使用make的“vpath”關(guān)鍵字(注意這里全小寫的),這不是變量,這是一個make的關(guān)鍵字,這和上面提到的那個VPATH變量很類似,但是它更為靈活。它可以指定不同的文件在不同的搜索目錄中。這是一個很靈活的功能。它的使用方法有三種:

1、vpath?<pattern>;?<directories>;

為符合模式<pattern>;的文件指定搜索目錄<directories>;。
?????? 2、vpath?<pattern>;
?????? 清除符合模式<pattern>;的文件的搜索目錄。
?????? 3、vpath
?????? 清除所有已被設(shè)置好了的文件搜索目錄。
??? vapth使用方法中的<pattern>;需要包含“%”字符。“%”的意思是匹配零或若干字符,例如,“%.h”表示所有以“.h”結(jié)尾的文件。<pattern>;指定了要搜索的文件集,而<directories>;則指定了<pattern>;的文件集的搜索的目錄。例如:
????vpath?%.h?../headers
該語句表示,要求make在“../headers”目錄下搜索所有以“.h”結(jié)尾的文件。(如果某文件在當前目錄沒有找到的話)我們可以連續(xù)地使用vpath語句,以指定不同搜索策略。如果連續(xù)的vpath語句中出現(xiàn)了相同的<pattern>;,或是被重復(fù)了的<pattern>;,那么,make會按照vpath語句的先后順序來執(zhí)行搜索。如:
????vpath?%.c?foo
????vpath?%??blish
????vpath?%.c?bar
其表示“.c”結(jié)尾的文件,先在“foo”目錄,然后是“blish”,最后是“bar”目錄。
????vpath?%.c?foo:bar
????vpath?%???blish
而上面的語句則表示“.c”結(jié)尾的文件,先在“foo”目錄,然后是“bar”目錄,最后才是“blish”目錄。

?

七、偽目標(也稱“假想目標”)

先看這兩行代碼:

clean:
????????????rm?*.o?temp
??? 正像我們前面例子中的“clean”一樣,我們并不生成“clean”這個文件。“偽目標”并不是一個文件,只是一個標簽,由于“偽目標”不是文件,所以make無法生成它的依賴關(guān)系和決定它是否要執(zhí)行。我們只有通過顯示地指明這個“目標”才能讓其生效。當然,“偽目標”的取名不能和文件名重名,不然其就失去了“偽目標”的意義了。
??? 當然,為了避免和文件重名的這種情況(make無法區(qū)分文件形式的目標和偽目標),我們可以使用 “.PHONY”來顯示地指明一個目標是“偽目標”,向make說明,不管是否有這個文件,這個目標就是“偽目標”,還讓make知道,不應(yīng)該像處理一般規(guī)則那樣,從源文件來建立以下以工作目標為名的文件。因此,make可以優(yōu)化它的一般規(guī)則搜索程序以提高性能。
????.PHONY?:?clean
??? 只要有這個聲明,不管是否有“clean”文件,要運行“clean”這個目標,只有“make?clean”這樣。于是整個過程可以這樣寫:
?????.PHONY:?clean
????clean:
????????????rm?*.o?temp
??? 偽目標一般沒有依賴的文件。但是,我們也可以為偽目標指定所依賴的文件。偽目標同樣可以作為“默認目標”,只要將其放在第一個。一個示例就是,如果你的Makefile需要一口氣生成若干個可執(zhí)行文件,但你只想簡單地敲一個make完事,并且,所有的目標文件都寫在一個Makefile中,那么你可以使用“偽目標”這個特性:
????all?:?prog1?prog2?prog3
????.PHONY?:?all
????prog1?:?prog1.o?utils.o
????????????cc?-o?prog1?prog1.o?utils.o
????prog2?:?prog2.o
????????????cc?-o?prog2?prog2.o
????prog3?:?prog3.o?sort.o?utils.o
????????????cc?-o?prog3?prog3.o?sort.o?utils.o
??? 我們知道,Makefile中的第一個目標會被作為其默認目標。我們聲明了一個“all”的偽目標,其依賴于其它三個目標。由于偽目標的特性是,總是被執(zhí)行的,所以其依賴的那三個目標就總是不如“all”這個目標新。所以,其它三個目標的規(guī)則總是會被決議。也就達到了我們一口氣生成多個目標的目的。“.PHONY?:?all”聲明了“all”這個目標為“偽目標”。
??? 隨便提一句,從上面的例子我們可以看出,目標也可以成為依賴。所以,偽目標同樣也可成為依賴。看下面的例子:
????.PHONY:?cleanall?cleanobj?cleandiff
????cleanall?:?cleanobj?cleandiff
????????????rm?program
????cleanobj?:
????????????rm?*.o
????cleandiff?:
????????????rm?*.diff
“make?clean”將清除所有要被清除的文件。“cleanobj”和“cleandiff”這兩個偽目標有點像“子程序”的意思。我們可以輸入“make?cleanall”和“make?cleanobj”和“make?cleandiff”命令來達到清除不同種類文件的目的。

clean沒有依賴模塊,因為沒有時間標記可供比較,所以它總被執(zhí)行;它的實際意圖是引出后面的rm命令來刪除某些目標文件。我們看到rm命令以-開頭,這時即使表示make將忽略命令結(jié)果,所以即使沒有目標供rm命令刪除而返回錯誤時,make clean依然繼續(xù)向下執(zhí)行。

?

?

?摘自百度文庫

轉(zhuǎn)載于:https://www.cnblogs.com/wnnily/p/4558815.html

與50位技術(shù)專家面對面20年技術(shù)見證,附贈技術(shù)全景圖

總結(jié)

以上是生活随笔為你收集整理的Makefile总结的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。