GNU make 更新 .d 文件时的确切事件链是什么?

2023-12-30

考虑以下简单的 makefile:

#------------------------------#
#    List all object files     #
#------------------------------#
objects := main.o foo.o bar.o baz.o

#------------------------------#
#    Define pattern rule       #
#    for   *.c -> *.o          #
#------------------------------#
%.o: %.c
    $(CC) -c $(CFLAGS) $< -o $@

#------------------------------#
#    Define the rule to make   #
#    the end result            #
#------------------------------#
.PHONY all
all: myApp.elf

myApp.elf: $(objects)
    $(CC) $(objects) -o myApp.elf $(LFLAGS) $(LIBS)

如果你发出命令make all, GNU make 将从目标开始myApp.elf。它会考虑所有先决条件main.o, foo.o, bar.o and baz.o并尝试更新它们。

为此,make 使用 makefile 中间定义的模式规则。该模式规则扩展如下:

main.o: main.c
    $(CC) -c $(CFLAGS) main.c -o main.o

foo.o: foo.c
    $(CC) -c $(CFLAGS) foo.c -o foo.o

bar.o: bar.c
    $(CC) -c $(CFLAGS) bar.c -o bar.o

baz.o: baz.c
    $(CC) -c $(CFLAGS) baz.c -o baz.o

到目前为止,一切都很好。但您可以清楚地看到缺少依赖项(包括 h 文件)。

我发现一些资料来源推荐以下方法:

#------------------------------#
#    List all object files     #
#    and all dependency files  #
#------------------------------#
objects := main.o foo.o bar.o baz.o
deps := $(objects:.o=.d)

#------------------------------#
#    Define pattern rule       #
#    for   *.c -> *.o          #
#------------------------------#
%.o: %.c
    $(CC) -c $(CFLAGS) -MMD -MP $< -o $@

#------------------------------#
#    Define the rule to make   #
#    the end result            #
#------------------------------#
.PHONY all
all: myApp.elf

myApp.elf: $(objects)
    $(CC) $(objects) -o myApp.elf $(LFLAGS) $(LIBS)

-include $(deps)

我正在尝试理解这种方法。首先,GNU make 读取 makefile 并查找其他包含的 makefile(请参阅 GNU make 手册第 3.5 段“如何重新制作 Makefile”)。尝试更新它可以找到的每个包含的 makefile(在本例中为依赖文件main.d, foo.d, bar.d and baz.d) 在开始执行 makefile 之前。我在下图中总结了这一点:

 
enter image description here  

确切地。我没有看到任何将依赖文件指定为目标的规则。

请帮助我了解接下来实际发生的事情。请将您的答案写成一系列逐步的事件。如果能够深入了解此事,那就太好了。

Note:
当然,-MMD and -MP编译命令中的参数(请参阅中间的模式规则)导致创建依赖文件。但这个模式规则的目标是object- 文件,而不是依赖性-files.

Note:
我错误地认为 GNU make 有一个隐式规则在这里被激活。但感谢您的评论和回答,我现在知道这是错误的:-)


这是你跑步时会发生的事情make after make clean并且依赖文件尚不存在:

  1. make读取文本并到达-include指示。
  2. 对于每个参数-include指示make尝试找到以其为目标的规则并运行该规则。make这是处理的一部分-include指示。不会找到这样的规则,因为您没有提供。
  3. make尝试读取指定的文件-include指令并跳过那些不存在的指令(在本例中是所有指令)。
  4. make去构建项目,项目又创建那些*.d files.

如果你跑make again:

  1. [和之前一样]
  2. [和之前一样]
  3. 由于文件现在确实存在,make阅读它们。
  4. [和之前一样]

您可能会注意到这意味着make使用上次运行的依赖项,这正是它的工作原理。 依赖关系滞后于源文件的更改。 不过,这通常不会造成不便,当它确实发生时,可以使用删除依赖文件来修复构建。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

GNU make 更新 .d 文件时的确切事件链是什么? 的相关文章

随机推荐