Makefile编译原理 make 中的路径搜索_1

一.make中的路径搜索

问题:在实际的工程项目中,所有的源文件和头文件都放在同一个文件夹中吗?

实验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;
}	makefileOBJS := func.o main.ohello.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值的处理方式

- 当前文件夹找不到需要的文件时,VPATH就会被使用

- make会在VPATH指定的文件夹中依次搜索文件

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

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

OBJS := func.o main.oVPATH := inc srchello.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.oINC := 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解释器就得到了需要的文件,并根据规则中的模式替换,生成了最后的规则。

实验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.oINC := 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$ 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/678256.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

假期2.7

一、填空题 1、在下列程序的空格处填上适当的字句&#xff0c;使输出为&#xff1a;0&#xff0c;2&#xff0c;10。 #include <iostream> #include <math.h> class Magic {double x; public: Magic(double d0.00):x(fabs(d)) {} Magic operator(_ _const…

离开亚马逊7.5年后的真心话

每周跟踪AI热点新闻动向和震撼发展 想要探索生成式人工智能的前沿进展吗&#xff1f;订阅我们的简报&#xff0c;深入解析最新的技术突破、实际应用案例和未来的趋势。与全球数同行一同&#xff0c;从行业内部的深度分析和实用指南中受益。不要错过这个机会&#xff0c;成为AI领…

【开源】SpringBoot框架开发厦门旅游电子商务预订系统

目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块2.1 景点类型模块2.2 景点档案模块2.3 酒店管理模块2.4 美食管理模块 三、系统设计3.1 用例设计3.2 数据库设计3.2.1 学生表3.2.2 学生表3.2.3 学生表3.2.4 学生表 四、系统展示五、核心代码5.1 新增景点类型5.2 查询推荐的…

金和OA C6 RssModulesHttp.aspx SQL注入漏洞复现

0x01 产品简介 金和网络是专业信息化服务商,为城市监管部门提供了互联网+监管解决方案,为企事业单位提供组织协同OA系统开发平台,电子政务一体化平台,智慧电商平台等服务。 0x02 漏洞概述 金和OA C6 RssModulesHttp.aspx接口处存在SQL注入漏洞,攻击者除了可以利用 SQL 注入…

算法学习——LeetCode力扣二叉树篇3

算法学习——LeetCode力扣二叉树篇3 116. 填充每个节点的下一个右侧节点指针 116. 填充每个节点的下一个右侧节点指针 - 力扣&#xff08;LeetCode&#xff09; 描述 给定一个 完美二叉树 &#xff0c;其所有叶子节点都在同一层&#xff0c;每个父节点都有两个子节点。二叉树…

「C++ 类和对象篇 11」explicit关键字

目录 〇、构造函数还具有类型转换的作用 一、explicit关键字是什么&#xff1f; 二、为什么需要explicit关键字&#xff1f; 三、怎么使用explicit关键字&#xff1f; 【总结】 〇、构造函数还具有类型转换的作用 构造函数不仅可以构造与初始化对象&#xff0c;对于只有一个参…

ChatGpt报错:Your authentication token is no longer valid解决办法

今天打开ChatGpt突然提示Oops&#xff01;,Your authentication token is no longer valid.&#xff0c;之前还好好的&#xff0c;环境也没变啊&#xff0c;结果弄了好久终于解决&#xff0c;于是记录一下解决过程&#xff0c;顺便总结一下关于OpenAI各种报错的解决办法。 完整…

Python编程-二万字浅谈装饰器原理与装饰器设计模式和函数式编程案例讲解

Python编程-浅析装饰器原理与装饰器设计模式和函数式编程案例讲解 本文制作时基于Python3.11.8与Python3.12.1&#xff0c;存在谬误&#xff0c;请联系修改&#xff0c;希望对你有所帮助 什么是函数式编程 函数式编程&#xff08;Functional Programming&#xff09;是一种编程…

【linux温故】linux调度机制

假如你是设计者&#xff0c;你会设计怎样的调度机制呢&#xff1f; 时间片 最简单的&#xff0c;小学生都能想出来的一种&#xff0c;每个 ready task&#xff0c;按照一个固定的时间片轮流执行。 大家不要抢&#xff0c;挨个儿排队执行。执行完时间片&#xff0c;就排在后面…

Linux发行版全景:选择、使用和未来趋势

1. 引言 Linux操作系统的简介 Linux是一种自由和开源的操作系统内核&#xff0c;由Linus Torvalds在1991年首次发布。随着时间的发展&#xff0c;Linux已经成为世界上最流行的操作系统之一&#xff0c;广泛用于服务器、桌面电脑、移动设备以及嵌入式系统。Linux的主要特点是其…

漫漫数学之旅017

文章目录 经典格言数学习题古今评注名人小传&#xff08;一&#xff09;亚当斯密&#xff08;二&#xff09;J理查德高特三世 经典格言 科学是热情与迷信之毒的最佳解毒剂。——亚当斯密&#xff08;Adam Smith&#xff09; 咳咳&#xff0c;各位看官&#xff0c;且听我用轻松…

POC集合,框架nday漏洞利用

综合 主流供应商的一些攻击性漏洞汇总 2021_Hvv漏洞 2022年Java应用程序的CVE漏洞 漏洞库合集 公开的信息、漏洞利用、脚本 Goby POC nuclei-templates LiqunKit_ 强化fscan的漏扫POC库 在渗透测试中快速检测常见中间件、组件的高危漏洞。 OAExploit一款基于产品的一…

【HTTP】localhost和127.0.0.1的区别是什么?

目录 localhost是什么呢&#xff1f; 从域名到程序 localhost和127.0.0.1的区别是什么&#xff1f; 域名的等级划分 多网站共用一个IP和端口 私有IP地址 IPv6 今天在网上逛的时候看到一个问题&#xff0c;没想到大家讨论的很热烈&#xff0c;就是标题中这个&#xff1a; …

吹响AI PC号角!微软在Windows中不断增加“Copilot含量”

2024&#xff0c;会是AI PC元年吗&#xff1f;至少微软正在往这个方向努力。 本周&#xff0c;微软开始在Windows中测试Copilot的“新体验”&#xff0c;其中包括任务栏中的Copilot图标&#xff0c;当用户复制文本或图片时&#xff0c;Copilot操作菜单就会自动出现。 有媒体在…

C#面:什么是Code-Behind技术

Code-Behind技术是一种在Web开发中常用的技术&#xff0c;它将前端页面与后端代码分离&#xff0c;使得前端页面的设计和后端代码的逻辑处理可以分别进行。在Code-Behind模式下&#xff0c;前端页面通常是一个标记语言&#xff08;如HTML或ASPX&#xff09;&#xff0c;而后端代…

Zotero常用插件分享

Zotero有着强大的文献管理功能&#xff0c;之前也对其进行过简要介绍&#xff08;Zotero——一款文献管理工具&#xff09;&#xff0c;而安装一些必要的插件则可以使其如虎添翼&#xff0c;今天一起来探索一下一些实用的插件吧&#xff01;&#xff08;排名不分先后&#xff0…

肯尼斯·里科《C和指针》第12章 使用结构和指针(2)双链表

12.3 双链表 单链表的替代方案就是双链表。在一个双链表中&#xff0c;每个节点都包含两个指针——指向前一个节点的指针和指向后一个节点的指针。这可以使我们以任何方向遍历双链表&#xff0c;甚至可以随意在双链表中访问。下面的图展示了一个双链表。 下面是节点类型的声明&…

java设计模式- 建造者模式

一 需求以及实现方式 1.1 需求描述 我们要创建一个表示汽车的复杂对象&#xff0c;汽车包含发动机、轮胎和座椅等部分。用传统方式创建&#xff0c;代码如下 1.2 传统实现方式 1.抽象类 public abstract class BuildCarAbstaract {//引擎public abstract void buildEng…

Spring Boot使用easy poi

Spring Boot使用easy poi 前言使用打完收工&#xff01; 前言 工作中需要每个月生成数据的报表&#xff0c;使用Excel展示数据。生成Excel肯定需要使用apache poi&#xff0c;但是我们可以直接使用easy poi&#xff0c;帮我们封装好了具体细节&#xff0c;但是使用起来有些细节…

python健身房管理系统 django健身课程预约系统

系统所要实现的功能分析&#xff0c;对于现在网络方便的管理&#xff0c;系统要实现用户可以直接在平台上进行查看首页、健身课程、留言板、个人中心、后台管理等&#xff0c;根据自己的需求可以进行查看健身课程&#xff0c;这样既能节省用户的时间&#xff0c;不用在像传统的…