在实际的工程项目中,源文件和头文件都会组织成一定的目录结构,这样也便于项目的管理,前述我们分析的makefile,源文件和头文件大都在当前目录,没有路径搜索的问题,下面我们引入今天的演示程序的目录结构:
 
编写makefile并执行make,结果如下:
 
由于源文件和头文件都组织在了文件夹里,但是make解释器却一无所知,因此,只能报错找不到对应的文件。
我们可以引入特殊的预定义变量VPATH,具体如下:
 
make对于VPATH值得处理方式如下:
1、当前文件夹找不到需要的文件时,VPATH会被使用。
2、make会在VPATH指定的文件夹中依次搜索文件。
3、当多个文件夹存在同名文件时,选择第一次搜索到的文件。
 
修改makefile,添加VPATH,执行make结果如下:
 
我们可以看到,这次是gcc报的错误,提示找不到func.h,虽然我们指定了VPATH搜索路径,但是这只是用于告诉make解释器去哪里寻找文件,gcc在预处理时,依然不知道头文件在何处。我们需要通过gcc的-I选项来告诉gcc去哪里寻找头文件。
更改后的makefile和执行结果如下:
 
小知识:gcc 编译时可以使用 -I 选项指定头文件的搜索路径, GCC的预处理器在实际操作时,会首先去 -I 选项指定的路径下搜索头文件,搜索不到时,再去与源文件相同的路径下搜索,还是搜索不到的话就报错。
 
通过VPATH变量,我们解决了路径搜索的问题,但是VPATH是个双刃剑,如果由于误操作我们将源文件放到了inc文件夹中,那在实际编译时可能就会得到意想不到的结果。
我们可以使用vpath关键字来代替VPATH变量,它具有更好的效果:
 
vpath关键字的使用比较灵活,可以设置搜索路径,也可以取消搜索路径的设置,如下所示:
 
如果只写一个vpath关键字,则取消所有已经设置的搜索规则。
 
我们来考察一些VPATH和vpath的常见问题:
1、当VPATH和vpath同时出现时,make会如何处理?考虑如下的项目结构:
 
上述项目结构对应的makefile以及执行结果如下:
 
src1和src2文件夹中都有func.c文件,由以上的实验现象可知,make首先搜索src2,当src2中func.c不存在时,make再去搜索src1。实验结论如下:
 
2、当使用vpath同时对一个模式指定多个文件夹时,make会如何处理?
在上一个makefile程序中做简单修改,并执行make,结果如下:
 
可见这次首先搜索的是src1文件夹,只有在src1文件夹中索搜不到时才会去src2文件夹中搜索。
结论如下:
 
3、通过VPATH指定搜索路径后,make如何决定目标文件的最终位置
编写如下的makefile,执行make,目标文件生成到了当前目录,如下所示:
 
将app.out移到src中,再次执行make,提示文件是最新的。可见make解释器在执行解释前,先在当前目录下搜索是否存在app.out,如果不存在,则根据VPATH的指示,去src文件夹搜索是否存在app.out,如果存在,则对比与依赖文件的新旧关系,然后决定是否执行重新编译链接。
 

VPATH的具体解释如下:
VPATH变量:
    VPATH变量指定搜索路径,例如,指定为src,此时,若src下和当前路径下没有目标文件,则在当前路径下生成;若src下有目标文件,
且新旧关系不变,则不会重新生成目标文件;若src下有目标文件,且新旧关系已经改变,则在当前文件夹下生成目标文件。   
    当同时指定GPATH为src,此时,若src下和当前路径下没有目标文件,则在当前路径下生成;若src下有目标文件,
且新旧关系不变,则不会重新生成目标文件;若src下有目标文件,且新旧关系已经改变,则在src文件夹下生成目标文件。
 
小结:
   1、尽量使用vpath为不同文件指定搜索路径。
   2、不要在源码文件夹中生成目标文件。
   3、为编译得到的结果创建独立的文件夹。
   4、工程中尽量避免VPATH和GPATH特殊变量的使用。
 
参考如下:
   狄泰软件教程及课件

   gun make手册
   专业嵌入式软件开发
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

第十六篇 make中的路径搜索的更多相关文章

  1. Egret入门学习日记 --- 第十六篇(书中 6.10~7.3节 内容)

    第十六篇(书中 6.10~7.3节 内容) 昨天搞定了6.9节,今天就从6.10节开始. 其实这个蛮简单的. 这是程序员模式. 这是设计师模式. 至此,6.10节 完毕. 开始 6.11节. 有点没营 ...

  2. 解剖SQLSERVER 第十六篇 OrcaMDF RawDatabase --MDF文件的瑞士军刀(译)

    解剖SQLSERVER 第十六篇 OrcaMDF RawDatabase --MDF文件的瑞士军刀(译) http://improve.dk/orcamdf-rawdatabase-a-swiss-a ...

  3. Python之路【第十六篇】:Django【基础篇】

    Python之路[第十六篇]:Django[基础篇]   Python的WEB框架有Django.Tornado.Flask 等多种,Django相较与其他WEB框架其优势为:大而全,框架本身集成了O ...

  4. Android UI开发第二十八篇——Fragment中使用左右滑动菜单

    Fragment实现了Android UI的分片管理,尤其在平板开发中,好处多多.这一篇将借助Android UI开发第二十六篇——Fragment间的通信. Android UI开发第二十七篇——实 ...

  5. 跟我学SpringCloud | 第十六篇:微服务利剑之APM平台(二)Pinpoint

    目录 SpringCloud系列教程 | 第十六篇:微服务利剑之APM平台(二)Pinpoint 1. Pinpoint概述 2. Pinpoint主要特性 3. Pinpoint优势 4. Pinp ...

  6. 四十六、android中的Bitmap

    四十六.android中的Bitmap: http://www.cnblogs.com/linjiqin/archive/2011/12/28/2304940.html 四十七.实现调用Android ...

  7. Python自动化 【第十六篇】:JavaScript作用域和Dom收尾

    本节内容: javascript作用域 DOM收尾 JavaScript作用域 JavaScript的作用域一直以来是前端开发中比较难以理解的知识点,对于JavaScript的作用域主要记住几句话,走 ...

  8. Flask最强攻略 - 跟DragonFire学Flask - 第六篇 Flask 中内置的 Session

    Flask中的Session非常的奇怪,他会将你的SessionID存放在客户端的Cookie中,使用起来也非常的奇怪 1. Flask 中 session 是需要 secret_key 的 from ...

  9. Struts2(十六篇)

    (一)Struts2框架概述 (二)Struts2配置文件 (三)Struts2的Action(简单讲解版) (四)Struts2的Action(深入讲解版) (五)Struts2处理结果管理 (六) ...

随机推荐

  1. Cocos2d-x学习笔记(五)调度

    在init方法中增加下边的代码,建议使用schedule函数,而不是scheduleUpdate函数,因为,后者默认是调用update函数,在如果有多个函数需要调度时,不是很灵活. auto labe ...

  2. SQLServer随机取记录

    SQLServer本身并没有提供随机读取记录的功能,但我们可以通过一些方法来实现这个目的.本文介绍了其中几种方法并比较了各自的优劣. 方法一:直接通过Sql语句实现,如: SELECT TOP 100 ...

  3. Jmeter性能测试之一 性能测试的流程和步骤介绍

    Step1: 知道在架构上,你要做的性能测试要cover几个部分,如下图,性能测试从用户角度,PC端之后都要要考虑进行的,例如网络,app server,Database等等 N1+N2+N3+N4 ...

  4. windows服务部署

    1.新建windows服务项目 2.编辑业务代码 我这里只写2句记录文本的测试代码 using System; using System.IO; using System.ServiceProcess ...

  5. 装B必备之 快捷键配置

    作为一个程序员 所有程序都用快捷来这是装B必备的无形装B 最为致命.... 开始搞起 第一步配置环境变量 在系统D盘新建一个文件夹  D:\cache; 然后把这个路径 配置上 D:\cache; 最 ...

  6. [don't have permission to access]的一个经典原因

    那就是 ..... SELinux ...... 几年前好像经历过这个恶梦.现在又经历了一回. 从Windows上传了一个目录,做一个apache的别名Alias, 结果总是没有权限. chmod 7 ...

  7. HTTP URL 字符转义 字符编码 、 RFC 3986编码规范

    一.为什么要编码转义 通常如果一样东西需要编码,说明这样东西并不适合传输.原因多种多样,如Size过大,包含隐私数据,对于Url来说,之所以要进行编码,是因为Url中有些字符会引起歧义. 例如Url参 ...

  8. 绑定任意格式的XML文档到WPF的TreeView

    Code highlighting produced by Actipro CodeHighlighter (freeware)http://www.CodeHighlighter.com/--> ...

  9. English trip M1 - PC12 I'd Like a Room Please Teacher:Taalan

    In this lesson you will learn to say what you need. 在本课中,您将学习如何说出您的需求. Words list elevator  电梯      ...

  10. Confluence 6 使用 LDAP 授权连接一个内部目录概述

    你可以为你的 Confluence 连接 LDAP 服务器使用使用委托认证.这个意思是 Confluence 将会设置一个内部目录,这个目录仅被用来处理 LDAP 的授权. 这个设置将会为尝试登录系统 ...