Makefile17 -- make 中的路径搜索(上)

本文深入探讨Makefile中的VPATH与vpath功能,通过实验展示如何解决跨目录文件引用问题,包括如何正确配置路径,避免同名文件冲突,以及确保编译器正确找到头文件。

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


实验1 : VPATH 引子
实验2 VPATH 初体验, VPATH 只能决定 make 的搜索路径,无法决定命令的搜索路径
实验3:指定编译命令gcc 需要的文件的搜索路径
实验4:当多个文件夹存在同名文件时,选择第一次搜索到的文件
实验5:vpath(小写) 初探

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

实验1 : VPATH 引子

mhr@ubuntu:~/work/makefile1/17$ ll
total 28
drwxrwxr-x 4 mhr mhr 4096 Apr 22 00:46 ./
drwxrwxr-x 7 mhr mhr 4096 Apr 22 00:32 ../
drwxrwxrwx 2 mhr mhr 4096 Jan 23  2018 inc/
-rw-rw-r-- 1 mhr mhr  133 Apr 22 00:46 makefile
drwxrwxrwx 2 mhr mhr 4096 Jan 23  2018 src/
mhr@ubuntu:~/work/makefile1/17$ 


inc/func.h

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

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

src/func.c

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

void foo()
{
    printf("void foo() : %s\n", HELLO);
}

src/main.c

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

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

makefile

OBJS := func.o main.o

hello.out : $(OBJS)
	@gcc -o $@ $^
	@echo "Target File ==> $@"

$(OBJS) : %.o : %.c func.h
	@gcc -o $@ -c $^

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

当前makefile: 要创建的可执行程序 hello.out 依赖于 func.o main.o 两个目标文件,这两个目标文件是通过 规则中的模式替换:

$(OBJS) : %.o : %.c func.h
	@gcc -o $@ -c $^

生成的,所以 make 就回去当前的文件夹下寻找需要的源文件,显然是找不到的。

在这里插入图片描述

注意:VPATH 是用于指导 make 查找文件的,并不指导gcc

在这里插入图片描述

如果 make 在当前的工作目录查找不到需要的文件,make 就会去查看 变量VPATH的值,如果VPATH 提供了文件夹的名字,那么make 就会去VPATH变量中的文件夹中找到有没有自己需要的文件。注意 make 会在VPATH变量中指定的文件夹中依次查找需要的文件,当多个文件夹存在同名文件时,选择第一次搜索到的文件,也就说假如如下场景:

VPATCH := dir1;dri2

dir1 和 dir2 中 同时存在 源文件test.c , 那么 make将以 dir1 中的 test.c 为准

实验2 VPATH 初体验, VPATH 只能决定 make 的搜索路径,无法决定命令的搜索路径

OBJS := func.o main.o

VPATH := inc src

hello.out : $(OBJS)
	@gcc -o $@ $^
	@echo "Target File ==> $@"

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


mhr@ubuntu:~/work/makefile1/17$ 
mhr@ubuntu:~/work/makefile1/17$ make
src/main.c:2:18: fatal error: func.h: No such file or directory
 #include "func.h"
                  ^
compilation terminated.
makefile:11: recipe for target 'main.o' failed
make: *** [main.o] Error 1
mhr@ubuntu:~/work/makefile1/17$ 

显然,这次没有提示: make: *** No rule to make target ‘func.c’, needed by ‘func.o’. Stop.的错误,说明 maka找到了 需要的源文件,即

$(OBJS) : %.o : %.c func.h
找到了 需要的源文件,但是该规则的命令却执行失败。

原因:VPATH 只能决定 make 的搜路径,无法决定命令的搜索路径,他对命令没有任何作用,上面得到的编译错误是因为 gcc 在编译.c文件的时候
找不到对应的头文件

在这里插入图片描述

实验3:指定编译命令gcc 需要的文件的搜索路径

OBJS := func.o main.o

INC := inc
SRC := src
VPATH := $(INC) $(SRC)
CFLAGS := -I $(INC)

hello.out : $(OBJS)
	@gcc -o $@ $^
	@echo "Target File ==> $@"

$(OBJS) : %.o : %.c func.h  // 为 make 提供搜索路径 :VPATH := $(INC) $(SRC)
	@gcc $(CFLAGS) -o $@ -c $<  //为 gcc 命令 提供搜索路径,搜索 func.h:-I $(INC)

$(OBJS) : %.o : %.c func.h // 为 make 解释器提供搜索路径 :VPATH := $(INC) $(SRC) ,这样make解释器就得到了需要的文件,并根据规则中的模式替换,生成了最后的规则

在这里插入图片描述

但是 规则中的命令,却找不到已经得到的.c文件中的头文件的位置,所以如下:
@gcc $(CFLAGS) -o $@ -c $< //为 gcc 命令 提供搜索路径,搜索 func.h:-I $(INC)

在这里插入图片描述

实验4:当多个文件夹存在同名文件时,选择第一次搜索到的文件

假如 inc 头文件文件夹中由于手误也存入了一个 func.c 那么会发生什么

inc/ func.h func.c
这里的func.c 内容如下:

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

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

makefile:

OBJS := func.o main.o

INC := inc
SRC := src
VPATH := $(INC) $(SRC)
CFLAGS := -I $(INC)

hello.out : $(OBJS)
	@gcc -o $@ $^
	@echo "Target File ==> $@"

$(OBJS) : %.o : %.c func.h  // 为 make 提供搜索路径 :VPATH := $(INC) $(SRC)
	@gcc $(CFLAGS) -o $@ -c $<  //为 gcc 命令 提供搜索路径,搜索 func.h:-I $(INC)


mhr@ubuntu:~/work/makefile1/17$ ./hello.out 
void foo() : This file is from inc ...
mhr@ubuntu:~/work/makefile1/17$ 

VPATH 变量告诉make解释器,当在当前目录找不到需要的文件的时候 首先到 inc文件夹中找,如果找不到 再去src文件夹中去找。如果在inc文件夹中找到了需要的文件,那么就不会继续去src文件夹中寻找了。但是inc 中的文件是我们手误放进去的,所以不是我们想要的结果,那么这种情况怎么办呢?

在这里插入图片描述

即说明 .h 头文件在 inc文件夹中去找; .c文件到 src文件夹中去找

实验5:vpath(小写) 初探

OBJS := func.o main.o
INC := inc
SRC := src
CFLAGS := -I $(INC)

vpath %.h $(INC)
vpath %.c $(SRC)

hello.out : $(OBJS)
	@gcc -o $@ $^
	@echo "Target File ==> $@"

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

mhr@ubuntu:~/work/makefile1/17$ 
mhr@ubuntu:~/work/makefile1/17$ ./hello.out 
void foo() : Hello D.T.
mhr@ubuntu:~/work/makefile1/17$ 

在这里插入图片描述

在这里插入图片描述

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

Ma浩然

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

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

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

打赏作者

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

抵扣说明:

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

余额充值