makefile(07)_路徑搜索

17.Make中的路徑搜索_上

17.0.實驗素材

源文件位于: src目錄下
源文件:main.c

創(chuàng)新新互聯(lián),憑借十年的網(wǎng)站制作、做網(wǎng)站經(jīng)驗,本著真心·誠心服務(wù)的企業(yè)理念服務(wù)于成都中小企業(yè)設(shè)計網(wǎng)站有成百上千家案例。做網(wǎng)站建設(shè),選成都創(chuàng)新互聯(lián)

#include <stdio.h>
#include "func.h"

int main()
{
    foo();

    return 0;
}   

源文件:func.c

#include <stdio.h>
#include "func.h"

void foo()
{
    printf("void foo() : %s\n", "Hello, D.T.Software ...");
}

頭文件位于: inc目錄下
頭文件func.c

#ifndef FUNC_H
#define FUNC_H

void foo();

#endif

17.1. 工程源碼組織方式

問題:實際的工程項目中,所有的源文件和頭文件都放在一個文件夾嗎?
實際的工程中,源碼和頭文件都是按照模塊劃分的,舉例如下:
makefile(07)_路徑搜索
項目中的makefile必須能夠正確的定位源文件和依賴文件,最終編譯產(chǎn)生可執(zhí)行程序。
實驗1:
當(dāng)源碼組織目錄如下時,下面的makefile能夠編譯成功嗎?
makefile(07)_路徑搜索

OBJS := func.o main.o

hello.out : $(OBJS)
    @gcc -o $@ $^
    @echo "Target File ==> $@"

$(OBJS) : %.o : %.c func.h
    @gcc  -o $@ -c $<

編譯結(jié)果:
makefile(07)_路徑搜索
由于make默認(rèn)只會在makefile所在的文件家去查找源文件和頭文件,所以自然會導(dǎo)致編譯報錯。

17.2. 預(yù)定義變量VPATH

VPATH變量的值用于指示make如何查找文件,不同文件夾可以作為VPATH的值同時出現(xiàn),可以使用空格,冒號,分號這樣的分隔符進(jìn)行分隔,如VPATH := src inc
實驗2:源碼目錄如下(注意這里存在兩個同名的C文件),下面的makefile編譯結(jié)果如何?
makefile(07)_路徑搜索

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 $<

編譯結(jié)果:
makefile(07)_路徑搜索
原因:VPATH只能決定make的搜索路徑,無法決定命令的搜索路徑,對特定編譯命令(gcc),需要獨立指定編譯搜索路徑。
makefile(07)_路徑搜索
修改makefile 內(nèi)容如下,再進(jìn)行實驗:

OBJS := func.o main.o
INC := inc
SRC := src
VPATH := $(INC) $(SRC)
CFLAGS := -I $(INC)

hello.out : $(OBJS)
    @gcc -o $@ $^
    @echo "Target File ==> $@"

$(OBJS) : %.o : %.c func.h
    @gcc $(CFLAGS) -o $@ -c $<

編譯和運行結(jié)果:
makefile(07)_路徑搜索
此時,我們看到編譯結(jié)果正確,但運行后發(fā)現(xiàn)被編譯的時inc目錄下的func.c文件,這可能不是我們預(yù)期的。
原因:當(dāng)make在當(dāng)前文件夾找不到需要的文件時,VPATH會被使用,make會在VPATH指定的文件夾中依次進(jìn)行搜索文件,當(dāng)多個文件夾存在同名文件時,選擇第一次搜索到的文件。
實驗3:
此時,我們講源文件中的.c文件更名為.cpp文件,進(jìn)行上面的實驗

當(dāng)inc文件夾意外出現(xiàn)文件(c/cpp文件),那么可能產(chǎn)生編譯錯誤。

17.3. vpath關(guān)鍵字

為了解決上面的問題,我們使用vpath關(guān)鍵字,為不同類型的文件指定不同的搜索路徑
語法:eg : vpath %.h inc或者 vpath %.h src
取消搜索路徑:
取消已經(jīng)設(shè)置的某個所搜規(guī)則:vpath patten,
eg: vpath %.h inc # 在inc中搜索.h文件
vpath %.h # 不再inc中搜索.h文件
取消所有已經(jīng)設(shè)置的規(guī)則
vpath

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 $<

17.4. 總結(jié):

VPATH變量用于指示make如何查找文件,make會在VPATH指定的文件夾中依次搜索文件
vpath 關(guān)鍵字可以為不同類型的文件指定不同的搜索路徑,比VPATH更靈活易用,可動態(tài)設(shè)置取消搜索路徑。

18.Make中的路徑搜索_下

18.1.VPATH和vpath同時使用

問題一:VPATH和vpath同時出現(xiàn)時,make會如何處理?
makefile(07)_路徑搜索

VPATH := src1
CFLAGS := -I inc

vpath %.c src2
vpath %.h inc

app.out : func.o main.o
    @gcc -o $@ $^
    @echo "Target File ==> $@"

%.o : %.c func.h
    @gcc $(CFLAGS) -o $@ -c $<

實驗結(jié)果:
makefile(07)_路徑搜索
實驗結(jié)論:
make首先在當(dāng)前文件夾搜索需要的文件,如果失?。?br/>Make優(yōu)先在vpath指定的文件夾中搜索目標(biāo)文件
當(dāng)vpath搜索失敗時,轉(zhuǎn)而搜索VPATH指定的文件夾

18.2.vpath對同一個patten指定多個文件夾

問題2:當(dāng)vpath對同一個patten指定多個文件夾時,make會如何處理?
makefile(07)_路徑搜索

CFLAGS := -I inc

vpath %.c src1
vpath %.c src2

vpath %.h inc

app.out : func.o main.o
    @gcc -o $@ $^
    @echo "Target File ==> $@"

%.o : %.c func.h
    @gcc $(CFLAGS) -o $@ -c $<

實驗結(jié)果:makefile(07)_路徑搜索
實驗結(jié)論:當(dāng)vpath對同一個patten指定多個文件夾時,make會依次自上而下,搜索指定的文件夾,直到找到目標(biāo)。

18.3.目標(biāo)文件位置

問題3:當(dāng)使用VPATH指定搜索路徑后,make如何確定最終目標(biāo)文件的位置?
下面的項目中,將如何生成可執(zhí)行程序?
makefile(07)_路徑搜索
實驗結(jié)論:
當(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)依賴關(guān)系改變時,如何使得src下的app.out被更新?

18.4.GPATH變量

上面問題,我們可以使用GPATH特殊變量指定目標(biāo)文件夾來解決。

GPATH := src
VPATH := src
CFLAGS := -I inc

app.out : func.o main.o
    @gcc -o $@ $^
    @echo "Target File ==> $@"

%.o : %.c inc/func.h
    @gcc $(CFLAGS) -o $@ -c $<

當(dāng)app.out完全不存在,make默認(rèn)在當(dāng)前文件夾創(chuàng)建app.out
當(dāng)app.out存在于src,并且依賴文件被更新,make在src文件夾中創(chuàng)建目標(biāo)文件
18.5.工程建議:
盡量使用vpath為不同文件指定搜索路徑;
不要在源碼文件夾中生成目標(biāo)文件,為編譯得到的結(jié)果創(chuàng)建獨立文件夾
盡量避免使用VPATH如果一定要使用,考慮GPATH的使用

19.Make中的路徑搜索_綜合示例

19.1.需求分析

工程項目中不希望源文件夾在編譯時被改動(只讀文件夾)
在編譯時自動創(chuàng)建文件夾(build)用于存放編譯結(jié)果
編譯過程中國能夠自動搜索到需要的文件
makefile易于擴(kuò)展,能夠復(fù)用相同類型的項目
支持調(diào)試版本和編譯選項

19.2.項目類型

makefile(07)_路徑搜索

19.3.工具原料:

$(wildcard $(DIR)/ _patten) 獲取$(DIR)文件夾中滿足_patten的文件
$(notdir _names) 去除_names中每一個文件名的路徑前綴
$(patsubst _patten, replacement, _text) 將_text中符合_patten的部分替換為replacement

19.4.關(guān)鍵技巧:

1.自動獲取文件列表(函數(shù)調(diào)用)
SRSC := $(waidcard src/*.c)
2.根據(jù)源文件列表生成目標(biāo)文件列表(變量的替換)
OBJS := $(SRC:.c=.o)
3.替換每一個目標(biāo)文件的路徑前綴(函數(shù)調(diào)用)
OBJS := $(patsubst src/%, build/%, $(OBJS))

19.5.編譯文件的依賴

makefile(07)_路徑搜索

19.6.最終方案:

.PHONY : all clean

DIR_BUILD := build
DIR_SRC := src
DIR_INC := inc

TYPE_INC := .h
TYPE_SRC := .c
TYPE_OBJ := .o

CC := gcc
LFLAGS :=
CFLAGS := -I $(DIR_INC)
ifeq ($(DEBUG),true)
CFLAGS += -g
endif

MKDIR := mkdir
RM := rm -fr

APP := $(DIR_BUILD)/app.out
HDRS := $(wildcard $(DIR_INC)/*$(TYPE_INC))
HDRS := $(notdir $(HDRS))
OBJS := $(wildcard $(DIR_SRC)/*$(TYPE_SRC))
OBJS := $(OBJS:$(TYPE_SRC)=$(TYPE_OBJ))
OBJS := $(patsubst $(DIR_SRC)/%, $(DIR_BUILD)/%, $(OBJS))

vpath %$(TYPE_INC) $(DIR_INC)
vpath %$(TYPE_SRC) $(DIR_SRC)

all : $(DIR_BUILD) $(APP)
    @echo "Target File ==> $(APP)"

$(DIR_BUILD) :
    $(MKDIR) $@

$(APP) : $(OBJS)
    $(CC) $(LFLAGS) -o $@ $^

$(DIR_BUILD)/%$(TYPE_OBJ) : %$(TYPE_SRC) $(HDRS)
    $(CC) $(CFLAGS) -o $@ -c $<

clean :
    $(RM) $(DIR_BUILD)

問題:
對于規(guī)模較小的項目,makefile是否也需要使用自動變量生成依賴關(guān)系的解決方案?
規(guī)模較小的項目沒必要使用自動生成依賴關(guān)系的解決方案,可以直接讓源文件依賴于頭文件(易于維護(hù))

19.7.總結(jié):

工程項目中不希望源碼文件夾在編譯時被改動
模式規(guī)則的靈活運用使得makefile具有復(fù)用性
變量的靈活運用使得makefile具有可擴(kuò)展性

分享題目:makefile(07)_路徑搜索
標(biāo)題路徑:http://muchs.cn/article40/jejgeo.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供微信小程序、搜索引擎優(yōu)化網(wǎng)站排名、App設(shè)計、品牌網(wǎng)站制作響應(yīng)式網(wǎng)站

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)

成都seo排名網(wǎng)站優(yōu)化