Makefile 里 VPATH 与 vpath 的用法可以参考 <<跟我一起写Makefile>> ,讲的很详细。
此处记录我在实际使用 VPATH 与 vpath 时遇见的问题。
我用了一个小 demo 来使用 VPATH,目录结构如下:
tmp
├── inc
│ └── sub.h
├── makefile
└── src
├── main.c
└── sub.c
main.c
和 sub.c
里都有 #include "sub.h"
。
1. 版本一
我的第一版 Makefile 如下:
VPATH = src:inc
test : main.o sub.o
gcc -o test main.o sub.o
main.o : main.c sub.h
gcc -c main.c
sub.o : sub.c sub.h
gcc -c sub.c
.PHONY: clean
clean:
rm *.o test
执行 make 命令后报错:
gcc -c main.c
gcc: error: main.c: No such file or directory
gcc: fatal error: no input files
compilation terminated.
make: *** [makefile:7: main.o] Error 1
仔细看上面那个 gcc 命令, gcc -c main.c ,初学者经常会认为,我都在 Makefile 文件里指定了搜寻路径为 "src:inc" 了,为什么会找不到 main.c 文件呢?main.c 文件不就是在 src/ 目录下么?
这就涉及到 VPATH 的概念理解了,
当 make 需要去找寻文件的依赖关系时,你可以在文件前加上路径,但最好的方法是把一
个路径告诉 make,让 make 在自动去找。
—— <<跟我一起写Makefile>>
VPATH 和 vpath 只是在 make 寻找文件的依赖关系时才有作用,而 gcc -c main.c 是你定义的规则所执行的命令,会原封不动地执行,该命令的意思是在当前文件夹下编译 main.c 文件,由于没有找到 main.c ,故出现上述错误。
使用 make -n 可以查看具体执行的命令:
gcc -c main.c
gcc -c sub.c
gcc -o test main.o sub.o
2. 版本二
第二版 Makefile 如下:
VPATH = src:inc
test : main.o sub.o
gcc -o test main.o sub.o
main.o : main.c sub.h
gcc -c $<
sub.o : sub.c sub.h
gcc -c $<
.PHONY: clean
clean:
rm *.o test
在执行命令时,使用 "$<" 这个自动变量,此时具体执行的命令如下,可以看见 gcc 编译的文件已经自动包含目录前缀了。
gcc -c src/main.c
gcc -c src/sub.c
gcc -o test main.o sub.o
不过上述 Makefile 仍然会报错:
gcc -c src/main.c
src/main.c:1:10: fatal error: sub.h: No such file or directory
1 | #include "sub.h"
| ^~~~~~~
compilation terminated.
make: *** [makefile:7: main.o] Error 1
错误信息提示我们编译时找不到 "sub.h" 头文件,观察上述执行的命令,发现需要添加自定义头文件路径,也就是 "-I" 选项。
3.版本三
VPATH = src:inc
test : main.o sub.o
gcc -o test main.o sub.o
main.o : main.c sub.h
gcc -c $< -I inc/
sub.o : sub.c sub.h
gcc -c $< -I inc/
.PHONY: clean
clean:
rm *.o test
具体执行的命令如下:
gcc -c src/main.c -I inc/
gcc -c src/sub.c -I inc/
gcc -o test main.o sub.o
该版本 Makefile 正常执行。
使用 VPATH 和 vpath 能够很好的组织我们的项目文件,有疑惑的地方欢迎在下方留言交流。