歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
Linux教程網 >> Linux編程 >> Linux編程 >> Makefile自動生成依賴,自動化編譯

Makefile自動生成依賴,自動化編譯

日期:2017/3/1 9:18:30   编辑:Linux編程

在netbeans裡開發,有一個重要文件makefile,是用來編譯所有的文件。

項目的目錄結構如下,扁平的目錄結構,如何實現自動化編譯,寫makefile呢?

第一版 基礎版:

CC = g++

CFLAGS = -O3 -DNDEBUG

SOURCE =AdaBoost.cpp aodeselect.cpp sample.cpp vfan.cpp kdbext2.cpp tan_gen.cpp

petal: ${SOURCE}

$(CC) -o $@ ${SOURCE} $(CFLAGS)

.PHONY:clean

clean:

rm -f petal.exe

簡簡單單,petal依賴所有的cpp,如果cpp有所修改那麼就會全部重新編譯,生成新的petal

十分耗時,大致需要

CFLAGS 就是傳給編譯器的編譯參數,定義成了一個變量

第二版

雛形版

CC = g++

CFLAGS = -O3 -DNDEBUG Debug版會使用參數-g;Release版使用-O3 –DNDEBUG

SOURCE =AdaBoost.cpp aodeselect.cpp sample.cpp變量的用法

default: petal 目標是生成default,要生成default,就要生成 petal ,規則沒寫,就是生成petal

echo "default"

depend: .depend 沒什麼用

echo "depend"

.depend: $(SOURCE) 依賴的是所有的.cpp 只要一個cpp文件有所修改 就要執行如下命令

echo ".depend"

rm -f ./.depend 刪除當前目錄下的.depend

$(CC) $(CFLAGS) -MM $^ >> ./.depend; -MM 自動找尋源文件中包含的非標准庫頭文件,並生成一個依賴關系 > 是定向輸出到文件,如果文件不存在,就創建文件;如果文件存在,就將其清空; >> 這個是將輸出內容追加到目標文件中。如果文件不存在,就創建文件;如果文件存在,則將新的內容追加到那個文件的末尾,該文件中的原有內容不受影響

$^--所有的依賴文件

.depend裡的示例內容如下:

naomiaode.o: naomi/naomiaode.cpp naomi/naomiaode.h \

naomi/../incrementalLearner.h naomi/../learner.h \

naomi/../instanceStream.h naomi/../instance.h naomi/../capabilities.h \

naomi/../xxxxyDist.h naomi/../xxxyDist.h naomi/../xxyDist.h \

naomi/../xyDist.h naomi/../smoothing.h naomi/../utils.h \

naomi/../mtrand.h naomi/../FILEtype.h naomi/../crosstab.h

其實就是找出source所有的cpp文件依賴的頭文件,並放到.depend裡

include .depend 要把.depend加進來

petal: ${SOURCE}

$(CC) -o $@ ${SOURCE} $(CFLAGS) g++ -o 目標可執行文件 源文件 參數

petal64: ${SOURCE} 沒有寫要生成它,毫無作用

$(CC) -o $@ ${SOURCE} $(CFLAGS) –DSIXTYFOURBITCOUNTS

輸出:

.depend文檔:

流程:

首先我遇到了include 就要先生成.depend文檔,生成完文檔後,把文檔中的.o與.c的依賴關系代替include指令,包括到makefile裡面來。所以要生成.depend對象,如果源代碼.cpp有所修改的話,就要刪除原來的.depend文檔,把依賴關系重新寫入文檔中。

Include階段結束

然後,最終目標是default,要生成default,就要生成依賴petal,要生成petal,看一看發現.cpp有所修改,重新全部編譯,刪去.o中間文件(直接 – a.cpp不會出現.o中間文件)

生成了petal,生成完petal後,就返回去生成deafault,所謂的生成default不是說我一定要真的-o deafault才好,我要有default.exe,不是這樣的,執行規則,就是生成對象,可惜default的規則,就是一條echo.那麼打印完字符串,default也就生成了

這一版本因為有要輸出所有頭文件依賴,耗時驚人 2m57s

而且白把依賴關系include進來了,可惜petal依賴的還是cpp文件,生成依賴關系毫無作用

第三版 自動化編譯 依賴.o 依賴於目標代碼:

我們把petal不依賴於cpp,不然每次都要全部重新編譯,不如依賴.o ,哪個cpp改了,就生成那個的.o,其它cpp的.o都不用動,編譯迅速

在舊版本的make中,使用編譯器此項功能通常的做法是:在Makefile中書寫一個偽目標"depend"的規則來定義自動產生依賴關系文件的命令。輸入"make depend"將生成一個稱為"depend"的文件,其中包含了所有源文件的依賴規則描述。Makefile使用"include"指示符包含這個文件。

這就是第二版的做法的初衷,depend對象也就是這麼來的,這樣petal依賴.o 再把.o依賴那些cpp和頭文件都包含進來,哪個cpp改了,從而要改哪個.o對象,也就明白了,那麼別的.o都不用重新編譯,連接起來是非常快的,而且可以利用隱含規則,不必寫如何通過.cpp和.h生成.o,十分爽

--------------------------------------分割線 --------------------------------------

u-boot Makefile完全解讀 http://www.linuxidc.com/Linux/2013-04/83529.htm

實驗平台上Makefile詳細的解釋 http://www.linuxidc.com/Linux/2014-01/94827.htm

Makefile之Linux內核模塊的Makefile寫法分析 http://www.linuxidc.com/Linux/2013-06/85842.htm

Makefile之寫demo時的通用Makefile寫法 http://www.linuxidc.com/Linux/2013-05/84679.htm

Makefile之大型工程項目子目錄Makefile的一種通用寫法 http://www.linuxidc.com/Linux/2013-05/84678.htm

--------------------------------------分割線 --------------------------------------

CC = g++

CFLAGS = -O3 -DNDEBUG

SOURCE = naomi/naomiaode.cpp naomi/naominbaode.cpp sampler.cpp trainTest.cpp ALGLIB_ap.cpp

OBJ= naomi/naomiaode.o naomi/naominbaode.o sampler.o trainTest.o ALGLIB_ap.o

default:petal 要注意的是要把目標放在第一個 一旦include進來之後,include進來的第一條目標naomi/naomiaode.o: naomi/naomiaode.cpp naomi/naomiaode.h \就是總目標了,所以就不以petal作為目標了

echo "default"

depend: .depend 可以使用make depend手動產生.depend依賴文件

echo "depend"

.depend: $(SOURCE)

echo ".depend"

rm -f ./.depend

$(CC) $(CFLAGS) -MM $^ >> ./.depend;

include .depend

petal: ${OBJ}

$(CC) -o $@ ${OBJ} $(CFLAGS)

.PHONY:clean

clean:

rm -f ${OBJ} petal.exe

現在makefile文件其實是這樣的:

.depend: $(SOURCE)

echo ".depend"

rm -f ./.depend

$(CC) $(CFLAGS) -MM $^ >> ./.depend;

Petal: naomi/naomiaode.o naomi/naominbaode.o sampler.o trainTest.o ALGLIB_ap.o

$(CC) -o $@ ${OBJ} $(CFLAGS)

現在petal依賴於.o,而.o 依賴於cpp 與 h,當修改一個cpp的時候,會重新生成.depend文件,包括進.o最新的依賴,然後檢查petal是否需要重新生成,petal依賴的naomi/naomiaode.o需要重新生成嗎?由於cpp的修改時間比.o的早,要重新生成.o petal依賴的sampler.o需要重新生成嗎?一個個檢查下去

比如我修改了

以下四個文件,而petal的依賴關系為:

petal:AdaBoost.o aodeselect.o sample.o vfan.o

所以會按序重新生成:

速度很快,但是這個版本還是有他自己的問題:

  1. 修改.h的時候,沒有重新生成.depend會出錯
  2. 修改一個.cpp,沒有必要重新產生所有cpp的依賴,依賴關系其實也像目標文件一樣,修改 了cpp或h的文件重新產生它的依賴關系,沒有修改的依賴關系不動。所以才有了.d文件版

當修改一個cpp的時候

,比如naomi/naomiaode.cpp

就要重新寫.depend文件,耗時較大

可以很明顯地看到,只重新編譯了naomiaode.cpp,耗時只有40s!!!! 從3分鐘降到40s秒,劃時代的進步,真正發揮了make的作用。

更多詳情見請繼續閱讀下一頁的精彩內容: http://www.linuxidc.com/Linux/2016-02/128726p2.htm

Copyright © Linux教程網 All Rights Reserved