我們在實際的工程項目中,所有的源文件和頭文件都放在同一個文件夾中嗎?如果是比較小的項目,當(dāng)然是可以的。但如果是成千上萬的源文件,當(dāng)然必須得分開存放。常用的源碼管理方式如下
公司主營業(yè)務(wù):成都做網(wǎng)站、網(wǎng)站建設(shè)、外貿(mào)營銷網(wǎng)站建設(shè)、移動網(wǎng)站開發(fā)等業(yè)務(wù)。幫助企業(yè)客戶真正實現(xiàn)互聯(lián)網(wǎng)宣傳,提高企業(yè)的競爭能力。創(chuàng)新互聯(lián)是一支青春激揚(yáng)、勤奮敬業(yè)、活力青春激揚(yáng)、勤奮敬業(yè)、活力澎湃、和諧高效的團(tuán)隊。公司秉承以“開放、自由、嚴(yán)謹(jǐn)、自律”為核心的企業(yè)文化,感謝他們對我們的高要求,感謝他們從不同領(lǐng)域給我們帶來的挑戰(zhàn),讓我們激情的團(tuán)隊有機(jī)會用頭腦與智慧不斷的給客戶帶來驚喜。創(chuàng)新互聯(lián)推出南湖免費(fèi)做網(wǎng)站回饋大家。
那么下面的 makefile 能夠編譯成功嗎?
我們來試試,編譯結(jié)果如下
那么結(jié)果肯定會是這樣的,因為我們在 makefile 中就沒有指定路徑,它在當(dāng)前目錄下沒有找到源文件。接下來我們就得來介紹一個特殊的預(yù)定義變量 VPATH (全大寫),VAPTH 變量的值用于指示 make 如何查找文件,不同文件夾可作為 VPATH 的值同時出現(xiàn),文件夾的名字之間需要使用分隔符進(jìn)行區(qū)分。格式如下
make 對于 VAPTH 值的處理方式:1、當(dāng)前文件夾找不到需要的文件時,VAPTH 會被使用;2、make 會在 VAPTH 指定的文件夾中依次搜索文件;3、當(dāng)多個文件夾存在同名文件時,選擇第一次搜索到的文件。注意事項:1、VAPTH 只能決定 make 的搜索路徑,無法決定命令的搜素路徑;2、對于特定的編譯命令(gcc),需要獨(dú)立指定編譯搜索路徑。如下
下來我們還是以代碼為例來進(jìn)行說明,在上面的 makefile 基礎(chǔ)上進(jìn)行改寫
OBJS := func.o main.o INC := inc SRC := src VPATH := $(INC) $(SRC) hello.out : $(OBJS) @gcc -o $@ $^ @echo "Target File ==> $@" $(OBJS) : %.o : %.c func.h @gcc -o $@ -c $^
我們來編譯試試看
我么你看到編譯還是報錯,原因就是我們在 gcc 的時候依賴文件中還包含有 func.h,下來我們將最后一行的 $^ 改為 $<。再來試試看
我們在編譯的時候,編譯器又報錯了,說是找不到 func.h。我們的 func.h 文件在 inc 文件中放著,編譯器并不知道去這個文件夾下找,只是在當(dāng)前文件下進(jìn)行查找?,F(xiàn)在就用到了我們上面說的為特定的編譯命令(gcc)獨(dú)立的指定編譯路徑。加上 CFLAGS := -I $(INC),并將 CFLAGS 變量加在 gcc 編譯的命令中。再來看看編譯結(jié)果
我們看到已經(jīng)正確編譯了,并且可執(zhí)行程序也完美運(yùn)行??此茊栴}完美的解決了,但其實 VPATH 也存在一定的問題,當(dāng) inc 文件夾中意外出現(xiàn)源文件(c/cpp 文件),那么可能就會產(chǎn)生編譯錯誤。我們?nèi)绻麑?func.c 誤放在 inc 文件夾中,這個 func.c 文件中打印的是 this is from inc ... ,看看會發(fā)生什么
我們看到輸出的竟然會是 inc 文件中的 func.c 的內(nèi)容,按照預(yù)想應(yīng)該是 hello makefile 啊。那么這時的解決方案便是利用 vpath 關(guān)鍵字(全小寫),它是為不同類型的文件指定不同的搜索路徑。語法是在 Directory 中搜索符合 Pattern 的規(guī)則的格式,格式如下
我們再次用 vpath 來進(jìn)行設(shè)置,看看編譯結(jié)果是怎樣的
我們看到已經(jīng)正確實現(xiàn)了。那么既然有設(shè)置這個規(guī)則,是否也可以有取消此規(guī)則的設(shè)置呢?當(dāng)然有了。在進(jìn)行某個具體搜索規(guī)則的取消時,是 vpath Pattern(如下圖);取消所有的設(shè)置規(guī)則時,直接 vpath 即可。
我們來試試,直接在下面加上 vpath %.h,代碼如下
OBJS := func.o main.o INC := inc SRC := src CFLAGS := -I $(INC) vpath %.h $(INC) vpath %.c $(SRC) hello.out : $(OBJS) @gcc -o $@ $^ @echo "Target File ==> $@" vpath %.h $(OBJS) : %.o : %.c func.h @gcc $(CFLAGS) -o $@ -c $<
編譯結(jié)果如下
我們看到編譯標(biāo)錯了,說找不到 func.h 頭文件啦。當(dāng)然找不到了,我們?nèi)∠?.h 頭文件的搜索路徑了。
下來我們來看看如果當(dāng) VPATH 和 vpath 同時出現(xiàn)時,make 會如何處理呢?如下
下面的項目中,會選擇哪一個文件夾進(jìn)行編譯?
我們還是以代碼為例來進(jìn)行編譯看看
VPATH := src1 CFLAGS := -I inc vpath %.c src2 vpath %.h inc app.out : func.o main.o @gcc -o $@ $^ @echo "Target File ==> $@" $(OBJS) : %.o : %.c func.h @gcc $(CFLAGS) -o $@ -c $<
編譯結(jié)果如下
我們看到它是按照 vpath 關(guān)鍵字指定的路徑下進(jìn)行編譯的。我們?nèi)绻麑?src2 文件夾中的 func.c 換成 func.cpp 呢,看看結(jié)果
我們看到:make 首先在當(dāng)前文件夾搜索需要的文件,如果失敗的話,make 優(yōu)先在 vpath 指定的文件夾中搜索目標(biāo)文件;當(dāng) vpath 搜索失敗時,轉(zhuǎn)而搜索 VPATH 指定的文件夾。如下
下來我們看看當(dāng)使用 vpath 對同一個 Pattern 指定多個文件夾時,make 會如何處理?如下
下面的項目中,會選擇哪一個文件夾進(jìn)行編譯?
我們來編譯看看結(jié)果
我們看到編譯的是第一個文件夾 src1 。make 首先在當(dāng)前文件夾搜索需要的文件,如果失?。簃ake 以自上而下的順序搜索 vpath 指定的文件夾,當(dāng)找到目標(biāo)文件,搜索結(jié)束。如下
下面來看看通過 VPATH 指定搜索路徑后,make 如何決定目標(biāo)文件的最終位置?下面的項目中,會選擇哪一個文件夾進(jìn)行編譯?
我們來看看編譯結(jié)果
我們看到生成可執(zhí)行程序 app.out。并且成功運(yùn)行。下來我們將 app.out 放入 src 文件夾中,重新 make,編譯器應(yīng)該是重新生成一個 app.out
它提示 app.out 是最新的,為什么沒有重新生成 app.out 呢?仔細(xì)分析下,在當(dāng)前文件夾下沒找到,但是編譯器不死心,繼續(xù)在 VPATH 變量指定的路徑下進(jìn)行尋找,終于在 src 文件夾下找到了 app.out,所以直接就不更新了。那么我們在 func.c 源文件中改變輸出的字符串為 hello D.T.Software 呢?看看結(jié)果
我們看到重新生成了一個 app.out,在 src 文件夾下的 app.out 是沒有改變的。但是在當(dāng)前目錄下又重新生成了一個 app.out 可執(zhí)行程序。當(dāng) app.out 完全不存在時,make 在當(dāng)前文件下創(chuàng)建 app.out。當(dāng) src 文件夾下存在 app.out 時,所有目標(biāo)和依賴的新舊關(guān)系不變,make 不會重新創(chuàng)建 app.out;當(dāng)依賴文件被更新,make 在當(dāng)前文件夾下創(chuàng)建 app.out。
那么問題就來了,當(dāng)依賴改變時,如何使得 src 下的 app.out 也被更新呢?解決方案便是使用 GPATH 特殊變量指定目標(biāo)文件夾;GPATH := src ,當(dāng) app.out 完全不存在時,make 默認(rèn)在當(dāng)前文件夾創(chuàng)建 app.out;當(dāng) app.out 存在于 src,且依賴文件被更新,make 在 src 中創(chuàng)建 app.out。下來還是以代碼為例來進(jìn)行說明
GPATH := src PATH := src CFLAGS := -I inc app.out : func.o main.o @gcc -o $@ $^ @echo "Target File ==> $@" %.o : %.c inc/func.h @gcc $(CFLAGS) -o $@ -c $<
編譯結(jié)果如下
在工程項目中:1、盡量使用 vpath 為不同文件指定搜索路徑;2、不要在源碼文件夾中生成目標(biāo)文件;3、為編譯得到的結(jié)果創(chuàng)建獨(dú)立的文件夾;4、避免 VPATH 和 GPATH 特殊變量的使用。 通過對 make 中的路徑搜索的學(xué)習(xí),總結(jié)如下:1、VPATH 變量用于指示 make 如何查找文件;2、make 會在 VPATH 指定的文件夾中依次搜索文件;3、vpath 關(guān)鍵字可以為不同類型的文件指定不同的搜索路徑;4、vpath 比 VPATH 更靈活易用,可動態(tài)設(shè)置/取消搜索路徑。
歡迎大家一起來學(xué)習(xí) makefile,可以加我QQ:243343083。