以下内容源于C语言中文网的学习与整理,非原创,如有侵权请告知删除。
前言
当源文件与 Makefile 文件的存放路径不同时,如何将源文件的路径告知Makefile文件呢?
方法有两种:一般搜索
VPATH,
选择搜索vpath
。两者的本质不同:VPATH 是环境变量,是Makefile 中的一种特殊变量,使用时需要指定文件的路径;而 vpath 是关键字,按照模式搜索,或者说选择搜索,搜索的时候不仅需要加上文件的路径,还需要加上相应限制的条件。
使用什么样的搜索方法,主要是基于编译器的执行效率。当路径下的文件较少,或者是搜索的文件不能使用通配符表示时,使用VPATH最好。但是如果路径下的文件很多,或者可以使用通配符时,建议使用vpath。因为 VPATH 在搜索文件时没有附加限制条件,它会检索目录下的所有文件,每一个文件都会进行对比,速度慢,效率低;而 vpath 搜索包含搜索条件,过滤掉那些不符合条件的文件,而从规定的条件中搜索目标,查找效率高。
VPATH的使用
在 Makefile 中可以这样写:
VPATH := src
把 src 的值赋值给变量 VPATH,在执行 make 的时候会从 src 目录寻找我们需要的文件。
当存在多个路径时,可以这样写:
VPATH := src car 或 VPATH := src:car
多个路径之间要使用空格或者是冒号隔开,表示在多个路径下搜索文件。搜索的顺序为我们书写时的顺序。
执行 make 时,先搜索当前目录下的文件,找到的话就使用当前目录下的文件,找不到的话才去 VPATH 指定的路径中寻找。
实例:
VPATH=src car test:test.ogcc -o $@ $^
假设 test.c 文件没有在当前的目录,而是在当前文件的子目录 "src" 或者是 "car" 下,程序执行也是没有问题的,但是生成的 test 文件是在当前的目录下。当然生成文件路径可以指定。
vpath的使用
vpath也被称作“选择性搜索”。VPATH 是搜索路径下所有的文件,而 vpath 更像是添加了限制条件,会过滤出一部分再去寻找。
PATTERN可以理解为要寻找的文件,而DIRECTORIES表示寻找的路径。
1、用法一
命令格式
vpath PATTERN DIRECTORIES
实例:在 src 路径下搜索文件 test.c。
vpath test.c src
多路径的书写规则如下:
vpath test.c src car 或 vpath test.c src : car
2、用法二
命令格式
vpath PATTERN
实例:清除符合文件 test.c 的搜索目录。(从搜索路径集中去掉将test.c文件所在的目录?)
vpath test.c
3、用法三
命令格式
vpath
vpath单独使用的意思是清除所有(已被设置的)文件搜索路径。
在使用 vpath 的时候,搜索的条件中可以包含模式字符“%”,这个符号的作用是匹配一个或者是多个字符,例如“%.c”表示搜索路径下所有的 .c 结尾的文件。
使用举例
src文件夹(list1.c、list2.c、main.c 文件)、include 文件夹(list1.h、list2.h 文件)、Makefile文件,这三者处于同层目录中。
其中Makefile 文件内容:
main:main.o list1.o list2.ogcc -o $@ $< main.o:main.cgcc -o $@ $^ list1.o:list1.c list1.hgcc -o $@ $< list2.o:list2.c list2.hgcc -o $@ $<
执行 make 时出现错误而编译停止,错误提示:
make:*** No rule to make target 'main.c',need by 'main.o'. stop.
重建最终目标文件 main 的时候需要 main.o 文件,然而去重建目标main.o 文件时,没有找到指定的 main.c 文件,这是错误的根本原因。所以我们可以为其添加文件搜索路径。
VPATH=src include #方法1 main:main.o list1.o list2.ogcc -o $@ $< main.o:main.cgcc -o $@ $^ list1.o:list1.c list1.hgcc -o $@ $< list2.o:list2.c list2.hgcc -o $@ $<
vpath %.c src vpath %.h include #方法2 main:main.o list1.o list2.ogcc -o $@ $< main.o:main.cgcc -o $@ $^ list1.o:list1.c list1.hgcc -o $@ $< list2.o:list2.c list2.hgcc -o $@ $<