外观
07.make中的路径搜索、路径搜索的综合示例
约 1769 字大约 6 分钟
路径搜索个人随笔记录
2022-06-20
第十七部分 :make 中的路径搜索(上)
17.1 问题
在实际的工程项目中,所有的源文件和头文件都放在同一个文件夹中吗?
17.2 常用的源码管理方式

项目中的makefile必须能够正确的定位源文件和依赖的文件,最终编译产生可执行程序。
17.3 下面的makefile能够成功编译吗?

17.4 特殊的预定义变量VPATH(全大写)
- vPATH变量的值用于指示make 如何查找文件
- 不同文件夹可作为VPATH的值同时出现
- 文件夹的名字之间需要使用分隔符进行区分

17.5 make 对于VPATH值的处理方式
- 当前文件夹找不到需要的文件时,VPATH会被使用
- make会在VPATH指定的文件夹中依次搜索文件
- 当多个文件夹存在同名文件时,选择第一次搜索到的文件
17.6 注意事项
- VPATH只能决定make的搜索路径,无法决定命令的搜索路径
- 对于特定的编译命令( gcc ) ,需要独立指定编译搜索路径

17.7 编程实验:VPATH的使用makefile.1
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 $<
17.8 VPATH存在的问题
inc文件夹中意外出现源文件( C / Cpp文件),那么可能产生编译错误!
17.9 替换方案:vpath关键字(全小写)
- 为不同类型的文件指定不同的搜索路径
- 语法︰
- 在Directory中搜索符合Pattern的规则的文件

17.10 取消搜索规则
- 取消已经设置的某个搜索规则
- .vpath Pattern
例: vpath %.h inc # 在inc中搜索.h文件
vpath %.h # 不再到inc中搜索.h文件
- 取消所有已经设置的规则
- vpath
17.11 编程实验:vpath的使用makefile.2
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.12 小结
- VPATH变量用于指示make 如何查找文件
- make 会在 VPATH 指定的文件夹中依次搜索文件
- vpath关键字可以为不同类型的文件指定不同的搜索路径
- vpath 比 VPATH 更灵活易用,可动态设置/取消搜索路径
第十八部分 :make 中的路径搜索(下)
18.1 问题一
当VPATH 和vpath同时出现时,make会如何处理?
VPATH := src1
vpath %.c src2
func.o : func.c
@echo "$^"
18.2 下面的项目中会选择哪一个文件进行编译?

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 $<18.3 编程实验:VPATH和vpath同时出现
Question1
18.4 实验结论
- make首先在当前文件夹搜索需要的文件
- 如果失败:
- make优先在vpath 指定的文件夹中搜索目标文件
- 当vpath 搜索失败时,转而搜索VPATH 指定的文件夹

18.5 问题二
当使用vpath对同一个Pattern指定多个文件夹时,make会如何处理?
vpath %.c src1
vpath %.c src2
func.o : func.c
@echo "$^"
18.6 下面的项目中会选择哪一个文件进行编译?

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 $<18.7 编程实验:vpath 指定多个文件夹
Question2
18.8 实验结论
- make首先在当前文件夹搜索需要的文件
- 如果失败:
- make 以自上而下的顺序搜索vpath指定的文件夹
- 当找到目标文件,搜索结束

18.9 问题三
通过VPATH指定搜索路径后,make如何决定目标文件的最终位置?
18.10 下面的项目中将如何生成可执行程序?

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 $<18.11 编程实验:搜索路径对目标的影响
Question3
18.12 实验结论
当app.out完全不存在∶
- make在当前文件下创建app.out
当src文件夹中存在app.out :
- 所有目标和依赖的新旧关系不变,make 不会重新创建app.out
- 当依赖文件被更新,make在当前文件夹下创建app.out
18.13 问题
当依赖改变时,如何使得src下的app.out被更新?
18.14 解决方案
- 使用GPATH特殊变量指定目标文件夹
- GPATH:= src
当app.out完全不存在
- make默认在当前文件夹创建app.out
当app.out存在于src ,且依赖文件被更新
- make在 src 中创建app.out
18.15 工程项目中的几点建议
- 尽量使用vpath为不同文件指定搜索路径
- 不要在源码文件夹中生成目标文件
- 为编译得到的结果创建独立的文件夹
- 避免VPATH和GPATH特殊变量的使用
第十九部分 :路径搜索的综合示例
19.1 需求分析
- 工程项目中不希望源码文件夹在编译时被改动(只读文件夹)
- 在编译时自动创建文件夹( build )用于存放编译结果
- 编译过程中能够自动搜索需要的文件
- makefile易于扩展,能够复用于相同类型的项目
- 支持调试版本的编译选项
19.2 项目类型分析

19.3 工具原料
$(wildcard $(DIR)/_pattern)
- 获取$(DIR)文件夹中满足_pattern的文件
$(notdir _names)
- 去除_names中每一个文件名的路径前缀
$(patsubst _pattern,replacement,_text)
- 将_text 中符合_pattern的部分替换为replacement
19.4 关键技巧
- 自动获取源文件列表(函数调用)
SRCS := $(wildcard src/* .c)
- 根据源文件列表生成目标文件列表(变量的值替换)
OBJS := $(SRCS: .c=.o)
- 替换每一个目标文件的路径前缀(函数调用)
OBJS := (patsubstsrc/(OBJS) )
19.5 编译规则的依赖

19.6 编程实验:综合示例makefile
19.7 值得斟酌的问题
对于规模较小的项目,makefile中是否也需要使用自动生成依赖关系的解决方案?
19.8 小结
- 工程项目中不希望源码文件夹在编译时被改动
- 模式规则的灵活运用使得makefile具有复用性
- 变量的灵活运用使得makefile具有扩展性
- 规模较小的项目没必要使用自动生成依赖关系的解决方案(取维护性牺牲效率)
- 规模较小的项目可以直接让源文件依赖于头文件(易于维护)
