2. vpath 指令和 VPATH 变量
本节课讲解两个内容:vpath 指令和 VPATH 变量。
vpath 指令是 Makefile 中的目录搜索机制,用于告诉 make 在哪些目录中查找源文件或依赖文件。 VPATH 变量 和 vpath 指令的作用基本相同,但 VPATH 只能全局统一设置,不能根据匹配模式进行精准控制。
为了说明上述内容,现在我们修改原来的程序文件的存放位置。我们分类将文件放入 include、src 和 task 三个文件夹中。
文件结构如下:
myapp2/
├── include
│ ├── file1.h
│ └── file2.h
├── src
│ └── main.c
└── task
│ ├── file1.c
│ └── file2.c
└── Makefile
现在我们在 Makefile 文件中,内容如下
.PHONY: all clean
SOURCES := main.c file1.c file2.c
HEADERS := file1.h file2.h
OBJECTS := main.o file1.o file2.o
TARGET := myapp2
all: $(TARGET)
$(TARGET) : $(OBJECTS)
gcc -o $@ $^
%.o : %.c $(HEADERS)
gcc -o $@ -c $< -I include
clean:
rm $(OBJECTS)
使用 make 命令编译,发送错误如下:
weimingze@mzstudio:~/myapp2$ make
make: *** 没有规则可制作目标“main.o”,由“myapp2” 需求。 停止。
上述 make 执行过程提示 main.o 没有找到。其原因是没有找到 main.c 来生成 main.o 因为 main.c 在文件夹 src 中。 make 命令只搜索当前文件夹,并不会搜索其更深层次的文件夹。要想让 make 能够搜索到其他文件夹有两种方法:
- 使用 vpath 指令。
- 使用 VPATH 变量。
1、vpath 指令
语法:
vpath 匹配模式 路径1:路径2:...
说明:
- 匹配模式可以使用百分号(
%)通配符进行模式匹配。 - 路径可以有一个或多个,中间用冒号(
:)分隔。 - 当有多个路径时,按先后顺序进行搜索。
- 如果没有给出任何路径,则取消当前匹配模式的 路径设置。
修改上述 Makefile 我们添加 vpath 指令如下:
# 指定 .c 文件在 src 和 task 文件夹中搜索
vpath %.c src:task
# 指定 .h 文件在 include 文件夹中搜索
vpath %.h include
修改后完整的 Makefile 如下:
.PHONY: all clean
# 指定 .c 文件在 src 和 task 文件夹中搜索
vpath %.c src:task
# 指定 .h 文件在 include 文件夹中搜索
vpath %.h include
SOURCES := main.c file1.c file2.c
HEADERS := file1.h file2.h
OBJECTS := main.o file1.o file2.o
TARGET := myapp2
all: $(TARGET)
$(TARGET) : $(OBJECTS)
gcc -o $@ $^
%.o : %.c $(HEADERS)
gcc -o $@ -c $< -I include
clean:
rm $(OBJECTS)
gcc的-I <路径>是指定头文件的位置
执行 Make的结果如下:
weimingze@mzstudio:~/myapp2$ make
gcc -o main.o -c src/main.c -I include
gcc -o file1.o -c task/file1.c -I include
gcc -o file2.o -c task/file2.c -I include
gcc -o myapp2 main.o file1.o file2.o
weimingze@mzstudio:~/myapp2$ ls
Makefile file2.o main.o src
file1.o include myapp2 task
由执行结果可以看出 gcc -o main.o -c src/main.c -I include 命令中 main.c 文件自动添加了路径 src/。
2、VPATH 变量
VPATH 变量是指定全局搜索路径,与 vpath 指令不同,他不能针对模式匹配的方式进行搜索路径的设置。
用法:
VPATH = 路径1:路径2:...
如,我们将上述示例中的 src、task 和 task 设置为VPATH的值。如下:
# 指定`src`、`task` 和 `task` 为全局搜索路径
VPATH = src:task:include
修改后的完整 Makefile 文件 如下:
.PHONY: all clean
# 指定`src`、`task` 和 `task` 为全局搜索路径
VPATH = src:task:include
SOURCES := main.c file1.c file2.c
HEADERS := file1.h file2.h
OBJECTS := main.o file1.o file2.o
TARGET := myapp2
all: $(TARGET)
$(TARGET) : $(OBJECTS)
gcc -o $@ $^
%.o : %.c $(HEADERS)
gcc -o $@ -c $< -I include
clean:
rm $(OBJECTS)
执行 Make的结果如下:
weimingze@mzstudio:~/myapp2$ make
gcc -o main.o -c src/main.c -I include
gcc -o file1.o -c task/file1.c -I include
gcc -o file2.o -c task/file2.c -I include
gcc -o myapp2 main.o file1.o file2.o
weimingze@mzstudio:~/myapp2$ ls
Makefile file2.o main.o src
file1.o include myapp2 task
可见使用 VPATH 和 vpath 实现了同样的效果。
实验:
分别使用 vpath 指令和 VPATH 变量来实现搜索路径的设置。