2. vpath 指令和 VPATH 变量

本节课讲解两个内容:vpath 指令VPATH 变量

vpath 指令是 Makefile 中的目录搜索机制,用于告诉 make 在哪些目录中查找源文件或依赖文件。 VPATH 变量vpath 指令的作用基本相同,但 VPATH 只能全局统一设置,不能根据匹配模式进行精准控制。

为了说明上述内容,现在我们修改原来的程序文件的存放位置。我们分类将文件放入 includesrctask 三个文件夹中。

文件结构如下:

myapp2/
├── include   ├── file1.h   └── file2.h
├── src   └── main.c
└── task   ├── file1.c   └── file2.c
└── Makefile

点击此处可以下载 上述文件夹的压缩包 myapp2.zip

现在我们在 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 能够搜索到其他文件夹有两种方法:

  1. 使用 vpath 指令
  2. 使用 VPATH 变量

1、vpath 指令

语法:

vpath 匹配模式 路径1:路径2:...

说明:

  1. 匹配模式可以使用百分号(%)通配符进行模式匹配。
  2. 路径可以有一个或多个,中间用冒号(:)分隔。
  3. 当有多个路径时,按先后顺序进行搜索。
  4. 如果没有给出任何路径,则取消当前匹配模式的 路径设置。

修改上述 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:...

如,我们将上述示例中的 srctasktask 设置为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 变量来实现搜索路径的设置。