Makefile18 -- make 中的路径搜索(下)

本文深入探讨了Makefile中VPATH、vpath及GPATH变量的使用,通过实验展示不同路径配置对源文件搜索的影响,以及如何正确设置以避免编译错误。

学习自狄泰软件学院唐佐临老师Makefile课程,文章中图片取自老师的PPT,仅用于个人笔记。


实验1 VPATH 和 vpath 同时指定搜索路径
实验2:当使用vpath 对.c文件指定多个文件夹时
实验3 使用GPATH 特殊变量指定目标文件夹


在这里插入图片描述

在这里插入图片描述

VPATH变量和vpath关键字同时指定搜索路径。

实验1 VPATH 和 vpath 同时指定搜索路径

mhr@ubuntu:~/work/makefile1/18$ tree
.
├── inc
│ └── func.h
├── main.c
├── makefile
├── src1
│ └── func.c
└── src2
└── func.c

makefile

VPATH := src1
CFLAGS := -I inc

vpath %.c src2
vpath %.h inc

app.out : func.o main.o
	@gcc -o $@ $^
	@echo "Target File ==> $@"

%.o : %.c func.h
	@gcc $(CFLAGS) -o $@ -c $<

main.c

#include <stdio.h>
#include "func.h"

int main()
{
    foo();
	
    return 0;
}	

src1/func.c

#include <stdio.h>
#include "func.h"

void foo()
{
    printf("void foo() : %s\n", "This file is from src1 ...");
}

src2/func.c

#include <stdio.h>
#include "func.h"

void foo()
{
    printf("void foo() : %s\n", "This file is from src2 ...");
}

inc/func.h

#ifndef FUNC_H
#define FUNC_H

void foo();

#endif


mhr@ubuntu:~/work/makefile1/18$ make
Target File ==> app.out
mhr@ubuntu:~/work/makefile1/18$ ./app.out 
void foo() : This file is from src2 ...
mhr@ubuntu:~/work/makefile1/18$ 

结果表明 当VPATH 和 vpath 同时指定搜索路径,优先选择 vpath 指定的所搜路径

改1:

将 src/func.c 改为 src/func.cpp 会发生什么?

.
├── inc
│ └── func.h
├── main.c
├── makefile
├── src1
│ └── func.cpp
└── src2
└── func.c

mhr@ubuntu:~/work/makefile1/18$ make
Target File ==> app.out
mhr@ubuntu:~/work/makefile1/18$ 
mhr@ubuntu:~/work/makefile1/18$ ./app.out 
void foo() : This file is from src2 ...
mhr@ubuntu:~/work/makefile1/18$ 

在这里插入图片描述
改2

├── inc
│ └── func.h
├── main.c
├── makefile
├── makefile.1
├── makefile.2
├── makefile.3
├── src1
│ └── func.cpp
└── src2
└── func.cpp

mhr@ubuntu:~/work/makefile1/18$ 
mhr@ubuntu:~/work/makefile1/18$ make
g++    -c -o func.o src1/func.cpp
src1/func.cpp:2:18: fatal error: func.h: No such file or directory
 #include "func.h"
                  ^
compilation terminated.
<builtin>: recipe for target 'func.o' failed
make: *** [func.o] Error 1
mhr@ubuntu:~/work/makefile1/18$ 

说明; 从 g++ 可以看出 ,make解释器启用了隐式规则,make 的行为如下:

但是,在当前目录下没有发现 .c文件,于是首先去vpath关键字指定的 src2中查找依赖文件,并没有找到,make继续到变量VPATH指定的文件夹中查找依赖文件,也没有找到需要的.c文件,至此应该报错了。但是make解释器并没有报错,因为他发现隐式规则中有一条规则可以 通过.cpp文件生成.o文件,于是make 开始查找func.cpp ,同样在当前目录下没有,于是首先去 关键字vpath指定的文件夹下搜索,但是make解释器发现vpath关键字没有指定 cpp 文件去哪儿找,所以make解释器又退而求其次的去 VPATH变量指定的文件夹下搜索 func.cpp文件,于是在 src1目录下找到了 func.cpp文件。于是开始通过g++编译器开始编译。但是在隐式规则中,并没有告诉g++命令到哪一个目录去寻找 .h 头文件,所以编译报错。

在这里插入图片描述

在这里插入图片描述

实验2:当使用vpath 对.c文件指定多个文件夹时

.
├── inc
│ └── func.h
├── main.c
├── makefile
├── src1
│ └── func.c
└── src2
└── func.c

makefile

CFLAGS := -I inc

vpath %.c src1
vpath %.c src2

vpath %.h inc

app.out : func.o main.o
	@gcc -o $@ $^
	@echo "Target File ==> $@"

%.o : %.c func.h
	@gcc $(CFLAGS) -o $@ -c $<



mhr@ubuntu:~/work/makefile1/18$ make
Target File ==> app.out
mhr@ubuntu:~/work/makefile1/18$ ./app.out 
void foo() : This file is from src1 ...
mhr@ubuntu:~/work/makefile1/18$ 

改1

├── inc
│ └── func.h
├── main.c
├── makefile
├── src1
│ └── func.cpp
└── src2
└── func.c

makefile

CFLAGS := -I inc

vpath %.c src1
vpath %.c src2

vpath %.h inc

app.out : func.o main.o
	@gcc -o $@ $^
	@echo "Target File ==> $@"

%.o : %.c func.h
	@gcc $(CFLAGS) -o $@ -c $<

mhr@ubuntu:~/work/makefile1/18$ 
mhr@ubuntu:~/work/makefile1/18$ make
Target File ==> app.out
mhr@ubuntu:~/work/makefile1/18$ ./app.out 
void foo() : This file is from src2 ...
mhr@ubuntu:~/work/makefile1/18$ 

先搜索src1,没有搜索到。再去搜索src2。

改2

├── inc
│ └── func.h
├── main.c
├── makefile
├── src1
│ └── func.cpp
└── src2
└── func.cpp

makefile

CFLAGS := -I inc

vpath %.c src1
vpath %.c src2

vpath %.h inc

app.out : func.o main.o
	@gcc -o $@ $^
	@echo "Target File ==> $@"

%.o : %.c func.h
	@gcc $(CFLAGS) -o $@ -c $<


mhr@ubuntu:~/work/makefile1/18$ make
make: *** No rule to make target 'func.o', needed by 'app.out'.  Stop.
mhr@ubuntu:~/work/makefile1/18$ 

因为 make 在当前路径,src1,src2中都找不到 func.c, 于是make 又发现因事规则中可以通过cpp文件生成.o文件,但是在makefile中 没有找到 哪个vpath关键字指明了有cpp文件,所以找不到文件报错。

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

实验3 VPATH变量提示去他指定的文件夹中搜索 在当前目录找不到的文件

├── inc
│ └── func.h
├── main.c
├── makefile
└── src
└── func.c

makefile

VPATH := src
CFLAGS := -I inc

app.out : func.o main.o
	@gcc -o $@ $^
	@echo "Target File ==> $@"

%.o : %.c inc/func.h
	@gcc $(CFLAGS) -o $@ -c $<



mhr@ubuntu:~/work/makefile1/18$ make
Target File ==> app.out
mhr@ubuntu:~/work/makefile1/18$ 

然后将生成的 app.out 拖到 src 下,这时候 根目录就没有 app.out了。此时make ,很多人会以为会在根目录重新生成一个 app.out ,可是实际效果如下:

mhr@ubuntu:~/work/makefile1/18$ make
make: 'app.out' is up to date.
mhr@ubuntu:~/work/makefile1/18$ 

因为此时make的编译决策是这样的:
make 之后,make解释器就会执行规则:

app.out : func.o main.o
	@gcc -o $@ $^
	@echo "Target File ==> $@"

于是 make 就开始对比 目标文件app.out 与 依赖文件之间的新旧关系,于是开始在当目录寻找app.out,但是没有找到,但是make可以去 VPATH变量指定的文件夹中搜索,于是在src 中找到了目标文件,对比 他与依赖的的时间戳,于是认为 不需要更新app.out。

改1

此时如果我们改动 src/func.c, 则一定会生成新的app.out, 但是make 并没有将生成的 app.out 放在 src 中去替换 他下面的app.out。而是放在的根目录!!!!

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
实验3 使用GPATH 特殊变量指定目标文件夹

GPATH := src
VPATH := src
CFLAGS := -I inc

app.out : func.o main.o
	@gcc -o $@ $^
	@echo "Target File ==> $@"

%.o : %.c inc/func.h
	@gcc $(CFLAGS) -o $@ -c $<

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Ma浩然

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值