1 疑问所在
博主在学习 <<“万能makefile”写法详解,一步一步写一个实用的Makefile>> 博文的时候,始终对于 Makefile include 的执行过程心存疑惑。 建议大家在看本博文之前,先看下提到的那篇博文。
有疑问的代码大致如下:
SRCS:$(wildcard *.c)
DEPS=$(SRCS:*.c=*.d)
.....
include $(DEPS)
%.d:%.c
gcc -MM $< > $@
疑问 : 若是首次 make,目录下不存在 xxx.d 文件,同时 xxx.d 文件并不是哪个规则的依赖文件,所以 <%.d:%.c> 这条模式规则应该不会执行,可实际上执行了,因为目录下生成了 xxx.d 文件。
结果 : 经过测试,发现首次 make 时,执行 include $(DEPS) 的时候,终端在报告了如下警告之后
makefile:6: xxx.d: No such file or dirctory
会默认在 makefile 中去找以 xxx.d 为目标的规则并执行,若该规则也没发现,便会报错并中止执行。
2 探索过程
以下是博主的测试过程,其 makefile 内容如下:
all:
@echo "-------- $@ ---------"
include tmp.d
tmp.d:
@echo "-------- $@ ---------"
make 执行结果如下:
makefile:6: tmp.d: No such file or directory
-------- tmp.d ---------
-------- all ---------
结果显示,执行了以 tmp.d 为目标的规则。
注释:all 目标才是首目标,可输出的结果是首先打印了tmp.d 目标,这是因为 include 语句执行于目标规则之前,好比 C 文件中的 include 指令一样。
-
倘若目录下存在 tmp.d, 会是什么情况呢?
先在 makefile 所在目录下执行命令 touch tmp.d 生成空文件 tmp.d
键入 make 执行结果如下:-------- all ---------
结果表明,当目录下存在 tmp.d 文件,则不会执行以 tmp.d 为目标的规则。
-
倘若 makefile 文件中没有以 tmp.d 为目标的规则,makefile 所在目录下也没有 tmp.d 文件,会出现什么情况呢?
现将 makefile 文件更新如下,屏蔽 tmp.d 规则:
all: @echo "-------- $@ ---------" include tmp.d #tmp.d: # @echo "-------- $@ ---------"
键入 make 执行结果如下:
makefile:6: tmp.d: No such file or directory make: *** No rule to make target `tmp.d'. Stop.
结果表明,一旦 makefile 所在目录下,没有 tmp.d 文件,且 makefile 中也没有以 tmp.d 为目标的规则,运行就会报错并终止,其实从错误消息的提示也可以看出,在运行到 include tmp.d 的时候,有如下两个动作:
**1. 检查 makefile 所在目录下是否有 tmp.d 文件;
- 查找 makefile 文件中是否有以 tmp.d 为目标的规则。**
若有一个符合都会执行通过。
实际开发过程中,对于使用了依赖文件的 makefile,不可能使用博文中提到的在首次 make 时,因为目录下不存在依赖文件,为了避免 include $(DEPS) 不报错或者警告而人工 touch 创建所有的依赖文件的。所以需要在 include 前面加上 ‘-’(忽略错误或警告),即如下处理:
-include $(DEPS)
-
倘若有两个连续的 include 目标,那么目标的执行顺序是怎样的了?
现更新 makefile 内容如下:
all: @echo "-------- $@ ---------" include tmp.d include dep.d tmp.d: @echo "-------- $@ ---------" dep.d: @echo "-------- $@ ---------"
键入 make 执行结果如下:
-------- dep.d --------- -------- tmp.d --------- -------- all ---------
由此可见,include 目标时,目标规则的执行顺序是从后往前执行。
3 结语
可能大牛会觉得以上实际过程本该如此,可是在我看了 <<跟我一起写Makefile>> 之后,还是对 include 关键字的理解不够全面,导致内心出现了文章开头所描述的疑惑。所以在此写给同样有如此疑问的新手,一起学习。