第18课 - make 中的路径搜索(下)

1. 问题一:当 VPATH 和 vpath 同时出现,make 会如何处理?

  工程项目的目录结构如下图所示,src1 和 src2 中都包含了 func.c 文件,如果在 makefile 中使用 VPATH 指定了 src1 ,使用 vpath 指定了 src2当 VPATH 和 vpath 同时存在时,make 会做出怎样的处理?

    

【编程实验】

makefile.1

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 $<
    

 

执行 make 后的输出结果:

  

 

【实验结论】

make 搜索文件的次序如下:

  make 首先在当前文件夹搜索需要的文件;如果搜索失败,make 优先 vpath 指定的文件夹中搜索目标文件;当 vpath 搜索失败时,转而搜索 VPATH 指定的文件夹。

    

 

2. 问题二:当使用 vpath 对同一个 Pattern 指定多个文件夹时,make 会如何处理?

工程项目的目录结构与问题一相同,src1 和 src2 中都包含了 func.c 文件,如果在 makefile 中使用 vpath 同时指定了两个src1 和 src2 两个目录,make 会做出怎样的处理?

  

【编程实验】

makefile.2

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 $<
    

 

 

执行 make 后的输出结果:(src1 出现在 src2 之前)

  

 

【实验结论】

makefile 中使用 vpath 对同一个 Pattern 指定了多个目录时,make 会以自上而下的顺序搜索 vpath 指定的文件夹,当找到目标文件时,搜索结束。

  

 

3. 问题三: 通过 VPATH 指定搜索路径后,make 如何决定目标文件最终位置

工程项目的目录结构如下图所示,查看 make 编译后当前目录下的内容,发现生成的可执行程序 app.out 在当前目录下

    

 

makefile.3

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 $<

 

 

如果此时把 app.out 移到 src 目录下,再次 make 编译,会出现什么样的情况?

    

当 make 编译时,发现 app.out 在当前目录下不存在,会搜索 VPATH 变量指定的路径,发现里面存在 app.out ,因此出现了上面的情况。

改动 fun.c 这个源文件,重新编译,发现在当前目录下生成了新的 app.out。

  

【实验结论】

(1)当 app.out 完全不存在

  • make 在当前文件下创建 app.out

(2)当 src 文件夹中存在 app.out

  • 所有目标和依赖的新旧关系不变,make 不会重新创建 app.out
  • 当依赖文件被更新,make 在当前文件夹下创建 app.out 

 

【问题】

  当依赖改变时,如何使得 src 下的 app.out 被更新?

 

【解决方案】

  使用 GPATH 特殊变量指定目标文件夹

     GPATH := src

  • 当 app.out 完全不存在时(当前目录和 src 中都不存在时),make 默认在当前文件夹创建 app.out。

  • 当 app.out 存在于 src 中,且依赖文件被更新,make 在 src 中创建 app.out

 

【工程项目中的几点建议】

(1)尽量使用 vpath 为不同文件指定搜索路径

(2)不要在源码文件中生成目标文件

(3)为编译得到的结果创建独立的文件夹

(4)避免 VPATH 和 GPATH 特殊变量的使用

 

4. 补充

make 的一个隐式规则以及 VPATH 变量可能会触发这个隐式规则。

  

假如当前目录下没有 main.c 这个文件,而有 main.cpp 这个文件,make 会有什么样的行为?

  

  可以看到当 make 找不到 main.c 文件时,发现依赖是 .o 文件,这就触发了 make 的隐式规则,寻找 main.cpp 文件并使用 g++ 进行编译。正好当前目录下有一个 main.cpp 文件,就产生了上图所示的结果。

  这一结果与 vpath 和 VPATH 联系起来,如果项目中使用 VPATH 指定的路径下有 xx.cpp ,而恰好又触发了上述的隐式规则,在原本应该报错的地方,make 却正常执行了。

  如果使用 vpath 就不会产生这种情况, vpath  %.c  dir这种方式只会寻找 .c 文件,因此 make 触发的隐式规则不会找到 xx.cpp 文件,程序会报错。

  从这个实验中可以得到一个项目经验,在实际的工程开发中,尽量使用 vpath 关键字而不使用 VPATH 变量,否则可能会产生意想不到的结果

 

posted @ 2019-01-06 16:58  梦心之魂  阅读(242)  评论(0编辑  收藏  举报