在实际的工程项目中,所有源文件和头文件都放在同一文件夹中吗?
常用的源码管理方式项目中的 makefile 必须能够正确的定位源文件和依赖的文件,最终编译产生可执行程序。
下面的 makefile 能编译成功吗?不能,当前目录下不存在对应的 .c 源文件。
特殊的预定义变量 VPATH (全大写)VPATH 变量的值用于指示 make 如何查找文件
不同文件夹可作为 VPATH 的值同时出现
文件夹的名字之间需要使用分隔符进行区分
make 对 VPATH 值的处理方式当前文件夹找不到需要的文件时,VPATH 会被使用
make 会在 VPATH 指定的文件夹中依次搜索文件
当多个文件夹同时存在同名文件时,选择第一次搜索到的文件
注意事项VPATH 只能决定 make 的搜索路径,无法决定命令的搜索路径
对于特定的命令 (gcc),需要独立指定编译搜索路径
VPATH 的使用makefile
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 $<
当前目录下的文件
当前目录下并不存在对应的源文件和头文件,我们使用 VPATH 指定了搜索路径,如果当前搜索不到对应的文件,就去指定路径下去搜索,gcc 命令需要使用 -I path 告诉它头文件的搜索路径。
VPATH 存在的问题当 inc 文件夹中意外出现源文件 (C / Cpp),那么可能产生编译错误!
替换方案:vpath 关键字 (全小写)为不同类型的文件指定不同的搜索路径
语法:
在 Directory 中搜索符合 Pattern 的规则的文件
取消搜索规则取消已经设置的某个搜索规则
vpath Pattern
取消所有已经设置的规则
vpath
vpath 的使用makefile
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 指定 .h 文件去 INC 目录下去找,.c 文件去 SRC 目录下去找。
问题一当 VPATH 和 vpath 同时出现时,make 会如何处理?
下面的项目中会选择哪一个文件进行编译?make 优先在 vpath 指定的文件夹中搜索目标文件
VPATH 和 vpath 同时出现makefile
INC := inc SRC1 := src1 SRC2 := src2 CFLAGS := -I $(INC) VPATH := $(SRC1) vpath %.c $(SRC2) vpath %.h $(INC) app.out : func.o main.o gcc -o $@ $^ %.o : %.c func.h gcc $(CFLAGS) -o $@ -c $<
运行结果如下所示:
可以看出 make 去 vpath 所指定的路径中去寻找 .c 文件了。
实验结论make 首先在当前文件夹搜索需要的文件
如果失败
make 优先在 vpath 指定的文件夹中搜索目标文件当 vpath 搜索失败时,转而搜索 VPATH 指定的文件夹
问题二当使用 vpath 对同一个 Pattern 指定多个文件夹时,make 会如何处理?
下面的项目中会选择哪一个文件进行编译? vpath 指定多个文件夹makefile
INC := inc SRC1 := src1 SRC2 := src2 CFLAGS := -I $(INC) vpath %.c $(SRC1) vpath %.c $(SRC2) vpath %.h $(INC) app.out : func.o main.o gcc -o $@ $^ %.o : %.c func.h gcc $(CFLAGS) -o $@ -c $<
运行结果如下所示:
make 选择了 src1 目录下的 func.c。
实验结论make 首先在当前文件夹搜索需要的文件
如果失败:
make 自上而下顺序搜索 vpath 指定的文件夹当找到目标文件搜索结束
问题三通过 VPATH 指定搜索路径后,make 如何决定目标文件的最终位置?
下面的项目将如何生成可执行程序? 搜索路径对目标的影响makefile
INC := inc SRC := src VPATH := $(SRC) # GPATH := $(SRC) CFLAGS := -I $(INC) app.out : func.o main.o gcc -o $@ $^ %.o : %.c $(INC)/func.h gcc $(CFLAGS) -o $@ -c $<
执行结果如下所示:
在当前目录下创建了 app.out
实验结论当 app.out 完全不存在:
make 在当前文件夹下创建 app.out
当 src 文件夹中存在 app.out:
所有目标和依赖的新旧关系不变,make 不会重新创建 app.out当依赖文件被更新。make 在当前文件夹下创建 app.out
问题当依赖改变时,如何使得 src 下的 app.out 被更新?
解决方案使用 GPATH 特殊变量指定目标文件夹
GPATH := src
当 app.out 完全不存在
make 默认在当前文件夹创建 app.out当 app.out 存在于 src,且依赖文件被更新
make 在 src 中创建 app.out
工程项目中的几点建议尽量使用 vpath 为不同文件指定搜索路径
不要在源码文件夹中生成目标文件
为编译得到的结果创建独立的文件夹
避免 VPATH 和 GPATH 特殊变量的使用



