make--路径搜索

make中的路径搜索

1、特殊的预定义变量VPATH(全大写)

  • VPATH变量的值用于指示make如何查找文件
  • 不同文件夹作为VPATH的值同时出现
  • 文件夹的名字之间需要使用分隔符进行区分
VPATH := inc src //空格作为分隔符
VPATH := inc;src //分号作为分隔符
VPATH := inc:src //冒号作为分隔符

make对于VPATH值的处理方式

  • 当前文件夹找不到需要的文件时,VPATH会被使用
  • make会在VAPTH指定的文件夹中依次搜索文件
  • 当多个文件夹存在同名文件时,选择第一次搜索到的文件

注意事项:

  • VPATH只能决定make的搜索路径,无法决定命令的搜索路径
  • 对于特定的编译命令(gcc),需要独立指定编译搜索路径
  • VPATH缺陷:
    当多个文件夹存在同名文件时,选择第一次搜索到的文件,可能会导致编译错误,选择的文件不一定是目标路径下的文件
gcc -I include-path
/*-I 编译选项,指定gcc的头文件搜索路径;
include-path 路径参数,gcc搜索的路径*/

**示例1–VPATH变量指定文件查找路径与gcc -I 指定头文件路径结合使用 **
./inc/func.h

#ifndef FUNC_H
#define FUNC_H

#define HELLO "hello world"

void foo();

#endif

./src/func.c

#include "func.h"

void foo()
{
	printf("void foo():%s\n",HELLO);	
}

./src/main.c

#include "stdio.h"
#include "func.h"

extern void foo();

int main()
{
	foo();

	return 0;
}

./makefile

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

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

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

在这里插入图片描述

2、关键字vpath(全小写)

  • 为不同类型的文件指定不同的搜索路径
  • 语法:
    在Directory中搜索符合Pattern规则的文件
vpath Pattern Directory
//例如:
vpath %.h inc
vpath %.c inc

** 示例2 vpath替换VPATH**
将示例1中makefile文件中的以下内容做替换:

VPATH := $(SRC) $(INC)
替换为
vpath %.h $(INC)
vpath %.c $(SRC)

可以解决VPATH变量的缺陷(多个文件夹中出现同名文件),make编译时从指定的文件夹下去找需要的文件,而不是选择第一次搜索到的文件。

  • 取消搜索规则
    • 取消已经设置的某个搜索规则
vpath Pattern
//例如:
vpath %.h inc //在inc中搜索.h文件
...
vpath %.h //不再到inc中搜索.h文件
  • 取消所有已经设置的规则
vpath

示例3–vpath关键字取消搜索规则
将示例1中的makefile增加语句:vpath %.h
,修改后的makefile文件如下:

//makefile

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

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

vpath %.h //不再到inc文件夹下搜索.h文件
$(OBJS) : %.o : %.c func.h
	@gcc $(CFLAGS) -o $@ -c $<

在这里插入图片描述
VPATH变量与vpath关键字小结:

  • VPATH变量用于指示make如何查找文件
  • make会在VPATH指定的文件夹中依次搜索文件
  • vpath关键字可以为不同类型的文件指定不同的搜索路径
  • vpath比VPATH更灵活易用,可动态设置/取消搜索路径
  • VPATH与vpath同时出现,make的搜索路径:
    • make首先在当前文件夹搜索需要的文件
    • 如果失败:
      • make优先在vpath指定的文件夹中搜索目标文件
      • 当vpath搜索失败时,转而搜索VPATH指定的文件夹
        示例4–make搜索路径–vpath与VPATH同时出现
//以下代码执行后,make搜索路径为:src2->src1->src3
VPATH := src1 src3
vpath %.c src2
  • 当使用vpath对同一个Pattern指定多个文件夹时,make的搜索路径:
    • make首先在当前文件夹搜索需要的文件
    • 如果失败:
      • make以自上而下的顺序搜索vpath指定的文件夹
      • 当找到目标文件,搜索结束;找不到则直接报错
//以下代码执行后,make搜索路径为:src3->src1->src2
vpath %.c src3
vpath %.c src1
vpath %.c src2
  • 通过VPATH指定搜索路径后,make如何决定目标文件的最终位置

4、路径搜索综合示例

(1)需求:

  • 工程项目中不希望源码文件夹在编译时改动(只读文件夹)
  • 在编译时自动创建文件夹(build)用于存放编译结果
  • 编译过程中能够自动搜索需要的文件 - makefile易于扩展,能够复用于相同类型的项目
  • 支持调试版本的编译选项

(2)项目结构

在这里插入图片描述

(3)工具原料

  • $(wildcard $(DIR)/ _pattern)
    • 获取$(DIR)文件夹中满足_pattern的文件
  • $(notdir _names)
    • 去除_names中每一个文件名的路径前缀
  • $(patsubst _pattern,replacement,_text)
    • 将_text中符合_pattern的部分替换为replacement

(4) 关键技巧

  • 自动获取源文件列表(函数调用)
    • SRCS := $(wildcard src/* .c)
  • 根据源文件列表生成目标文件列表(变量的值替换)
    • OBJS := $(SRCS:.c=.o)
  • 替换每一个目标文件的路径前缀(函数调用)
    • OBJS := ( p a t s u b s t s r c / (patsubst src/%,build/%, (patsubstsrc/(OBJS))

(5) 编译规则的依赖

在这里插入图片描述

makefile

.PHONY : all cleancd ..

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

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

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_SRC) $(DIR_SRC) 
vpath %$(TYPE_INC) $(DIR_INC) 

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

$(DIR_BUILD) :
	$(MKDIR) $@

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

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

clean :
	$(RM) $(DIR_BUILD)

在这里插入图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值