第17课 - make 中的路径搜索(上)

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

在以往的 make 学习中,我们使用到的 .c 文件和 .h 文件都与 makefile 处在同一个路径在实际的工程项目中,所有的源文件头文件都放在同一个文件夹中吗?

答案毋庸置疑是否定的,在实际的工程项目中,源文件和头文件的数量可能是成千上万的,必须采用一定的目录结构进行管理,一般按照模块的功能进行分类管理

      

  因此,实际工程项目中的 makefile 必须能够正确的定位源文件和依赖的文件,最终编译产生可执行程序。

 

2. 下面的 makefile 能够编译成功吗?

          

在 linux 下执行 make,产生错误提示找不到依赖对应的文件

  

 

3. make 中的路径搜索

3.1 特殊的预定义变量 VPATH(全大写)

(1) VPATH 是 make 的预定义变量,该变量的值用于指示 make 如何查找文件

(2)不同文件夹可作为 VPATH 的值同时出现

(3)文件夹的名字之间需要使用分隔符进行区分

  • 例1:VPATH := inc  src  (空格

  • 例2:VPATH := inc  src  (分号

  • 例3:VPATH := inc:src (冒号)  

 

3.2 make 对于 VPATH 值的处理方式

(1)当前文件夹找不到需要的文件时,VPATH 会被使用

(2)make 会在VPATH 指定的文件夹中依次搜索文件

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

 

3.3 注意事项(重点)

(1) VPATH 只能决定 make 的搜索路径无法决定命令的搜索路径

(2) 对于特定的编译命令(gcc),需要独立指定编译搜索路径。make 层面的路径和 gcc 层面的路径是两个不同环境下的路径。makefile 中的命令是在当前 make 启动的新的 shell 中运行的,所以命令的工作路径就是当前 make 的工作路径。

      

【编程实验】:解决本文第2点(下面的make能够编译成功吗?)出现的问题 makefile.1

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
    @gcc $(CFLAGS) -o $@ -c $<

 

 

执行 make 后程序的输出:

  

注意两点:

  (1) 观察 echo 打印的自动变量 $< 它们是 .c 文件所处的路径,而不是它们本身,这表明 make 会根据模式规则推导出真正的规则

      func.o : func.c     ==>     func.o : inc/func.c

  (2)编译 main.c 和 func.c 生成的 main.o 和 func.o 文件与 makefile 处在同一个目录下,这表明 gcc 默认生成的 .o文件放在其工作目录下

 

3.4 VPATH存在的问题及其解决方案

3.4.1 VPATH 存在的问题

  前面提到过,当多个文件夹存在同名文件时,选择第一次搜索到的文件。因为 makefile 中的 VPATH := (INC)(INC)(SRC)  变量首先包含的是 inc 目录,当 inc 文件夹中意外出现源文件时(C/Cpp文件),如 func.c 文件,那么就会使用该文件夹下同名的 func.c 文件,这就有可能产生编译错误

  

 
3.4.2 解决方案

使用 vpath 关键字(全小写)替换 VPATH 预定义变量(全大写)。这里注意 VPATH 是 make 的预定义变量,而 vpath 是 make 中的关键字,要能够区分两者。

  (1)vpath 不同类型的文件指定不同的搜索路径

  (2)语法:在 Directory 中搜索符合 Pattern 的规则的文件

       

  (3)取消搜索规则

   — 取消已经设置的某个搜索规则

    • vpath Pattern

       例:vpath   %.h  inc      # 在 inc 中搜索 .h 文件

         vpath   %.h        # 不再到 inc 中搜索 .h 文件

   — 取消所有已经设置的规则

    • vpath      

【编程实验】:vpath 的使用 makefile.2

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 ==> $@"
    
# vpath %.h

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

 

运行结果:

 

 

3. 小结

(1)VPATH 变量用于指示make如何查找文件

(2)make 会在VPATH 指定的文件夹中依次搜索文件

(3)vpath 不同类型的文件指定不同的搜索路径

(4)vpath VPATH 更灵活易用,可动态设置/取消搜索路径

 

posted @ 2018-11-21 19:19  梦心之魂  阅读(268)  评论(0编辑  收藏  举报