繁体   English   中英

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

[英]What is the exact chain of events when GNU make updates the .d files?

考虑以下简单的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.ofoo.obar.obaz.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之前,尝试更新它可以找到的每个包含的makefile(在本例中为依赖文件main.dfoo.dbar.dbaz.d )。 我在下图中总结了这一点:


在此处输入图片说明

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

请帮助我了解接下来会发生什么。 请把您的答案写成一个循序渐进的事件链。 这将是获得有关此事的见识的好方法。

注意:
当然,编译命令中的-MMD-MP参数(请参阅中间的模式规则)导致创建依赖文件。 但是此模式规则的目标是对象文件,而不是依赖文件。

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

没有内置的make规则.d文件。 您可以看到make确实考虑使用make -d重建.d文件,但是没有规则,例如:

Reading makefile 'test/debug/library.d' (search path) (don't care) (no ~ expansion)...
Updating makefiles....
 Considering target file 'test/debug/library.d'.
  File 'test/debug/library.d' does not exist.
  Looking for an implicit rule for 'test/debug/library.d'.
  No implicit rule found for 'test/debug/library.d'.
  Finished prerequisites of target file 'test/debug/library.d'.
 Must remake target 'test/debug/library.d'.
 Failed to remake target file 'test/debug/library.d'.

在上面的输出make检查是否library.d需要更新。 未能找到它的规则, make跳过更新它,看到的Makefile如何都经过了重组

...读完所有makefile文件后, make会将每个文件视为目标目标并尝试对其进行更新。 如果一个makefile有一条规则说明如何更新它(在那个makefile或另一个makefile中找到),或者如果一个隐式规则适用于它,则必要时将对其进行更新

这就是为什么它不会两次编译每个.c

您可以使用make --print-data-base打印所有规则,包括内置规则。

我将同时回答两个问题,因为这样做更有意义。

Make没有.d内置规则-它不需要一个。 -MMD -MP指示编译器输出依赖项,作为适当的编译的一部分。

如果您考虑到了这正是您想要的,因为唯一需要更新依赖项的就是相关源文件本身已经更改,如果在编译过程中生成了依赖项,则只需运行一次编译器即可生成依赖项.d.o文件。

难题的最后一部分是-include ,它告诉make如果可以找到依赖项,则包含make依赖关系,但不必担心它们是否不存在,它们还是会由编译器生成。

make clean和依赖文件尚不存在之后运行makemake clean发生以下情况:

  1. make读取文本并到达-include指令。
  2. 对于每个参数-include指令make试图找到具有它作为一个目标的规则和运行规则。 make-include指令的处理过程中执行此操作。 找不到这样的规则,因为您没有提供。
  3. make试图读取指定的文件-include指令,并只是跳过那些不存在的(所有的人在这种情况下)。
  4. make开始构建项目,该项目又创建了*.d文件。

如果再次运行make

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

您可能会注意到,这意味着make使用上一次运行的依赖关系,而这正是它的工作方式。 依赖关系落后于源文件中的更改。 但是,这通常不会带来任何不便,并且当确实删除依赖项文件时,可以用来修复构建。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM