当GNU更新.d文件时,确切的事件链是什么? [英] What is the exact chain of events when GNU make updates the .d files?

查看:168
本文介绍了当GNU更新.d文件时,确切的事件链是什么?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

考虑以下简单的makefile:

 #---------------- --------------#
#列出所有对象文件#
#-------------------- ----------#
objects:= main.o foo.o bar.o baz.o

#----------- -------------------#
#定义模式规则#
#用于* .c - > * .o#
#------------------------------#
%.o:%。 c
$(CC)-c $(CFLAGS)$ < -o $ @

#------------------------------#
#定义规则#
#最终结果#
#------------------------------#
.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 baz.o 并尝试更新它们。为此,make use在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文件)缺失。



我发现了一些推荐以下方法的源代码:

 #------------------------------#
#列出所有对象文件#
#和所有依赖文件#
#---------------------------- - #
objects:= main.o foo.o bar.o baz.o
deps:= $(objects:.o = .d)

# - ----------------------------#
#定义模式规则#
#用于* .c - > * .o#
#------------------------------#
%.o:%。 c
$(CC)-c $(CFLAGS)-MMD -MP $< -o $ @

#------------------------------#
#定义规则#
#最终结果#
#------------------------------#
.PHONY all
all:myApp.elf

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

- 包括$(deps)

我试图围绕这种方法来包装我的头。首先GNU make读取makefile并查找其他包含的makefile(请参阅GNU make手册第3.5节Makefile如何重新制作)。尝试更新它可以找到的每个包含的makefile(在这种情况下,依赖文件 main.d foo.d bar.d baz.d ),然后开始执行makefile。我在下图中总结了这一点:

 


 



正是。我没有看到任何依赖文件被指定为目标的规则。



请帮助我了解接下来会发生什么。请把你的答案写成一步一步的事件链。这很好,可以深入了解此事。

注意:

当然,<$ c $编译命令中的c> -MMD 和 -MP 参数(请参阅中间的模式规则)会导致创建相关性文件。但是这个模式规则的目标是 object -files,而不是 dependency -files。

注意:

我错误地认为GNU make的隐式规则在这里被激活。但是,由于您的意见和答案,我现在知道这是错误的: - ) 当运行 make make clean 并且依赖文件还不存在:


  1. make 读取文本并达到 -include 指令。

  2. 对于 -include 指令 make的每个参数会尝试找到一条规则,使其成为一个目标并运行该规则。 make 是作为处理 -include 指令的一部分。

  3. make 尝试读取<$ c $中指定的文件,因此不会找到这样的规则,因为您没有提供这样的规则。 c> -include 指令,并跳过那些不存在的指令(在这种情况下,所有这些指令)。 去建立项目,然后创建那些 *。d 文件。

如果您再次运行 make


  1. [相同由于文件确实存在,所以 make
  2. 读取它们。
  3. [与以前相同]

您可能会注意到这意味着 make 使用前一次运行的依赖关系,这正是它的工作原理。
依赖性落后于源文件的变化。
虽然这通常不会造成不便,并且在删除依赖文件时可用于修复构建。


Consider the following simple 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)

If you give the command make all, GNU make will start at the target myApp.elf. It looks at all the prerequisites main.o, foo.o, bar.o and baz.o and attempts to update them.

To do that, make uses the pattern rule defined in the middle of the makefile. This pattern rule expands like this:

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

So far, so good. But you can clearly see that dependencies (included h-files) are missing.

I found some sources that recommend the following approach:

#------------------------------#
#    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)

I'm trying to wrap my head around this approach. First GNU make reads the makefile and looks for other included makefiles (see GNU make manual paragraph 3.5 "How Makefiles Are Remade"). Make attempts to update each included makefile it can find (in this case the dependency files main.d, foo.d, bar.d and baz.d) before starting execution of the makefiles. I've summarized this in the following figure:

 
 

Exactly. I don't see any rule where the dependency files are specified as targets.

Please help me to understand what actually happens next. Please, write your answer as a step-by-step chain of events. That would be great to gain insight in the matter.

Note:
Of course, the -MMD and -MP arguments in the compilation command (see pattern rule in the middle) lead to dependency files getting created. But the targets of this pattern rule are the object-files, not the dependency-files.

Note:
I had wrongly assumed that GNU make has an implicit rule getting activated here. But thanks to your comments and answers, I now know this was wrong :-)

解决方案

Here's what happens when you run make after make clean and dependency files don't exist yet:

  1. make reads the text and reaches -include directive.
  2. For each argument of the -include directive make tries to find a rule that has it as a target and run that rule. make does this as part of processing of -include directive. No such rule will be found, because you didn't provide one.
  3. make attempts to read files specified in -include directive and just skips those which don't exist (all of them in this case).
  4. make goes to build the project, which in turn creates those *.d files.

If you run make again:

  1. [same as before]
  2. [same as before]
  3. Since files do exist now, make reads them.
  4. [same as before]

You might notice that this implies that make uses dependencies from the previous run, which is exactly how it works. Dependencies lag behind changes in the source files. This doesn't usually cause inconveniences though, and when it does removing dependency files can be used to fix the build.

这篇关于当GNU更新.d文件时,确切的事件链是什么?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆