源文件位于: 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
問題:實際的工程項目中,所有的源文件和頭文件都放在一個文件夾嗎?
實際的工程中,源碼和頭文件都是按照模塊劃分的,舉例如下:
項目中的makefile必須能夠正確的定位源文件和依賴文件,最終編譯產(chǎn)生可執(zhí)行程序。
實驗1:
當源碼組織目錄如下時,下面的makefile能夠編譯成功嗎?
OBJS := func.o main.o
hello.out : $(OBJS)
@gcc -o $@ $^
@echo "Target File ==> $@"
$(OBJS) : %.o : %.c func.h
@gcc -o $@ -c $<
編譯結(jié)果:
由于make默認只會在makefile所在的文件家去查找源文件和頭文件,所以自然會導致編譯報錯。
VPATH變量的值用于指示make如何查找文件,不同文件夾可以作為VPATH的值同時出現(xiàn),可以使用空格,冒號,分號這樣的分隔符進行分隔,如VPATH := src inc
實驗2:源碼目錄如下(注意這里存在兩個同名的C文件),下面的makefile編譯結(jié)果如何?
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é)果:
原因:VPATH只能決定make的搜索路徑,無法決定命令的搜索路徑,對特定編譯命令(gcc),需要獨立指定編譯搜索路徑。
修改makefile 內(nèi)容如下,再進行實驗:
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é)果:
此時,我們看到編譯結(jié)果正確,但運行后發(fā)現(xiàn)被編譯的時inc目錄下的func.c文件,這可能不是我們預期的。
原因:當make在當前文件夾找不到需要的文件時,VPATH會被使用,make會在VPATH指定的文件夾中依次進行搜索文件,當多個文件夾存在同名文件時,選擇第一次搜索到的文件。
實驗3:
此時,我們講源文件中的.c文件更名為.cpp文件,進行上面的實驗
當inc文件夾意外出現(xiàn)文件(c/cpp文件),那么可能產(chǎ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 $<
VPATH變量用于指示make如何查找文件,make會在VPATH指定的文件夾中依次搜索文件
vpath 關(guān)鍵字可以為不同類型的文件指定不同的搜索路徑,比VPATH更靈活易用,可動態(tài)設(shè)置取消搜索路徑。
問題一:VPATH和vpath同時出現(xiàn)時,make會如何處理?
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é)果:
實驗結(jié)論:
make首先在當前文件夾搜索需要的文件,如果失?。?br/>Make優(yōu)先在vpath指定的文件夾中搜索目標文件
當vpath搜索失敗時,轉(zhuǎn)而搜索VPATH指定的文件夾
問題2:當vpath對同一個patten指定多個文件夾時,make會如何處理?
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é)果:
實驗結(jié)論:當vpath對同一個patten指定多個文件夾時,make會依次自上而下,搜索指定的文件夾,直到找到目標。
問題3:當使用VPATH指定搜索路徑后,make如何確定最終目標文件的位置?
下面的項目中,將如何生成可執(zhí)行程序?
實驗結(jié)論:
當app.out完全不存在,make會在當前文件夾下創(chuàng)建app.out
當src文件夾下存在app.out:
所有目標和依賴的新舊關(guān)系不變,make不會重新創(chuàng)建app.out
當依賴文件被更新,make在當前文件夾下創(chuàng)建app.out
問題:當依賴關(guān)系改變時,如何使得src下的app.out被更新?
上面問題,我們可以使用GPATH特殊變量指定目標文件夾來解決。
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 $<
當app.out完全不存在,make默認在當前文件夾創(chuàng)建app.out
當app.out存在于src,并且依賴文件被更新,make在src文件夾中創(chuàng)建目標文件
18.5.工程建議:
盡量使用vpath為不同文件指定搜索路徑;
不要在源碼文件夾中生成目標文件,為編譯得到的結(jié)果創(chuàng)建獨立文件夾
盡量避免使用VPATH如果一定要使用,考慮GPATH的使用
工程項目中不希望源文件夾在編譯時被改動(只讀文件夾)
在編譯時自動創(chuàng)建文件夾(build)用于存放編譯結(jié)果
編譯過程中國能夠自動搜索到需要的文件
makefile易于擴展,能夠復用相同類型的項目
支持調(diào)試版本和編譯選項
$(wildcard $(DIR)/ _patten) 獲取$(DIR)文件夾中滿足_patten的文件
$(notdir _names) 去除_names中每一個文件名的路徑前綴
$(patsubst _patten, replacement, _text) 將_text中符合_patten的部分替換為replacement
1.自動獲取文件列表(函數(shù)調(diào)用)
SRSC := $(waidcard src/*.c)
2.根據(jù)源文件列表生成目標文件列表(變量的替換)
OBJS := $(SRC:.c=.o)
3.替換每一個目標文件的路徑前綴(函數(shù)調(diào)用)
OBJS := $(patsubst src/%, build/%, $(OBJS))
.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)系的解決方案,可以直接讓源文件依賴于頭文件(易于維護)
工程項目中不希望源碼文件夾在編譯時被改動
模式規(guī)則的靈活運用使得makefile具有復用性
變量的靈活運用使得makefile具有可擴展性
分享題目:makefile(07)_路徑搜索
標題路徑:http://m.rwnh.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)