1?什么是Makefile
? ? 在之前學(xué)習(xí)C程序的編譯過程中,我們知道編譯一個程序還比較簡單, 如果要編譯多個文件,或者不同文件夾中的文件,需要生成不同的庫文件,以及確定這些文件的編譯先后順序,往往所需要的命令行特別多,而且比較復(fù)雜,甚至對于以后項目的維護(hù)也比較麻煩。
? ? 再想想如果我們需要編譯Linux內(nèi)核這樣好幾W個文件的項目難道需要我們一個命令的輸入嗎 ? 那估計是一場噩夢。
?
? ? 那么這個時候如果我們能夠把所有的編譯規(guī)則全部規(guī)范到文件中,然后通過解析該文件去執(zhí)行對應(yīng)的編譯指令,這樣就大大簡化指令的復(fù)雜度,同時降低了編譯程序過程中所帶來的錯誤。
? ? 根據(jù)上面的需求就產(chǎn)生了Makefile,我們的編譯和處理規(guī)則就放在Makefile文件中,通過Makefile工具解析Makefile文件中的命令來指導(dǎo)整個工程的編譯過程。
? ? 當(dāng)然Makefile文件中的命令書寫是有一定的規(guī)范的,這也是今天我們所要講到的重點,一旦該文件編寫好以后在Linux命令行中執(zhí)行一條make命令即可自動編譯整個工程,不但提高了開發(fā)效率也便于后期維護(hù)。
? ? 當(dāng)然不同廠家的make稍有不同,并且語法上也有點區(qū)別,不過基本思想都差不多,主要還是落在目標(biāo)依賴上來,這里以最廣泛的GNU Make跟大家講解。
2?Makefile文件基本規(guī)則
? ? 上面的為大家展示了Makefile的核心規(guī)則,有點類似于一位廚師做菜,目標(biāo)就是做一碗好菜,那么所謂的依賴就是各種食材、各種廚具等等,然而有了這些依賴還不夠需要廚師有著非常好的廚藝才能做出一道好菜。
? ? 同時這些依賴也有可能此時此刻并不存在,需要現(xiàn)場制作,或者由其他廚師做好,那么這個依賴就成為了其他規(guī)則的目標(biāo),該目標(biāo)也會有它自己的依賴和命令,這樣形成一層一層遞歸依賴組成了Makefile文件。
? 總結(jié)
Makefile并不會關(guān)心命令是如何執(zhí)行的,僅僅只是會去執(zhí)行所定義的命令,和我們平時直接輸入命令行是一樣的效果。
Makefile就相當(dāng)于一個依賴關(guān)系文件,在執(zhí)行該文件的以后會遞歸的查找依賴文件并執(zhí)行對應(yīng)的命令,最終生成第一個目標(biāo)。
3?簡單使用Makefile
? ? 下面小哥就之前代碼簡單演示一下Makefile:
? ? 上圖是makefile文件,最終為了生成Test文件,需要三個*.o文件,然后三個.o文件又分別依賴于對應(yīng)的*.c文件,這樣加上對應(yīng)的gcc命令就構(gòu)成了一個基本的makefile。
? ? 注意 : 2/4/6/8行均為tab鍵。
? ? 下面使用make命令來編譯生成test目標(biāo)文件
? ? 這樣我們執(zhí)行make命令一鍵就搞定了所有的編譯任務(wù),如果下次需要改變編譯過程就直接修改對應(yīng)的makefile文件中的規(guī)則即可。
? ? 有類比過windows里面IDE環(huán)境中編譯器使用的小伙伴都知道在windows里面的開發(fā)工具編譯通過一鍵即可搞定所有編譯內(nèi)容。難道windows中的開發(fā)工具更強(qiáng)大一些?
? ? 其實不然,我們在windows中構(gòu)建對應(yīng)的工程文件的過程中通過圖形界面就悄悄的把類似的makefile文件給生成了,那么當(dāng)點擊編譯的時候就相當(dāng)于在命令行里面執(zhí)行make,其實都是類似的,僅僅只是我們平時使用windows更多一點,更加容易接受。
? ?當(dāng)然這里僅僅只是演示了一些最簡單的操作,比較麻煩的還是命令部分可以使用到通配符和shell指令等等,這樣會增加一定的復(fù)雜度,其實makefile本身并沒有太大的難度。
? ? 下一節(jié)小哥將為大家補(bǔ)充一些makefile更多便捷的操作,當(dāng)然現(xiàn)在也出現(xiàn)了許多類似于cmake這樣的便捷工具,不過其核心還是makefile!
4?指定使用Makefile文件
? ? 在命令行中使用make命令,makefile會在默認(rèn)路徑中查找對應(yīng)的makefile文件來進(jìn)行工程管理,我們一般把對應(yīng)的makefile文件名命名為Makefile和makefile等,如果名字不匹配可能無法找到對應(yīng)的makefile文件,比如:
makefile文件名
Makefile文件名
MAKEFILE文件名-編譯失敗
? 從上面的實驗現(xiàn)象可以了解到make會查找默認(rèn)的makefile文件名,如果沒有找到規(guī)定的文件名就會報相應(yīng)的故障。
? ? 不過如果平時在一個目錄下存在多個makefile文件的時候,一般我們都會通過不同命名來進(jìn)行區(qū)分,那么該如何指定對應(yīng)的makefile文件進(jìn)行識別解析呢 ?可以使用make -f選項,如下圖所示:
5?注釋文本
? ? 在開發(fā)過程中存在需要注釋掉makefile文件相應(yīng)文本行可以在文件的行首使用#號:
? ? 上面是正常進(jìn)行makefile編譯目標(biāo)文件的完整實例,并且輸出了正確的結(jié)果,然后小哥使用#號屏蔽掉前面兩行,如下圖所示:
? ? 繼續(xù)執(zhí)行make命令,根據(jù)makefile的規(guī)則,會默認(rèn)編譯Test1.o目標(biāo)文件:
? ? 這樣我們獲得了正確的結(jié)果,說明注釋生效。
6?取消回顯文本
? ? 在makefile使用過程中默認(rèn)是會把相應(yīng)的處理過程信息進(jìn)行回顯,這樣能夠讓開發(fā)者更好的了解makefile的處理過程.
??? 不過,如果回顯信息非常的龐大也是不利于開發(fā)者分析的,所以編輯人員可以使用@來取消相關(guān)信息的回顯,如下圖所示:
在命令tab鍵后加入@
??? 這里我們可以看到使用make以后沒有像之前使用的makefile文件那樣存在回顯的命令行信息了。
7?偽目標(biāo)的使用
? ? 在makefile文件中有時候執(zhí)行一些不需要有依賴命令的目標(biāo),稱為偽目標(biāo)。
? ? 上面是對應(yīng)的makefile文件,其中里面加入偽目標(biāo)clean,通過使用.PHONY修飾,這樣可以直接使用make clean 來執(zhí)行對應(yīng)的命令。
? ? 上面執(zhí)行make clean確實執(zhí)行了清除操作。
8?變量的使用
? ? 在makefile中為了減少代碼的重復(fù),使用變量的概念來簡化編寫,如下面的makefile進(jìn)行如下改造:
? ??使用$(obj)來代替所有的目標(biāo)文件,以后需要添加其他目標(biāo)文件的話就只需要在變量obj處進(jìn)行相應(yīng)修改即可。
? ??同時系統(tǒng)還存在其他默認(rèn)的自動化變量,這樣可以大大簡化makefile文件,便于設(shè)計和后期維護(hù),如:
$^??? 表示所有的依賴文件
$@ ?? 表示生成的目標(biāo)文件
$?? 代表第一個依賴文件
等等? ??
? ? makefile基礎(chǔ)知識點小哥暫時就講到這里,其實大部分工程項目自己完完全全編寫的并不是很多,更多的修修改改,所以遇到了具體的疑問在進(jìn)行查找或許效率更高。
審核編輯:劉清
評論
查看更多