生成文件说明

Makefile Explanation

我是 makefile 的新手,正在尝试理解一些代码:

%.o:%.c
    $(CC) $^ -c -Wall
    $(CC) -MM $*.c > $*.dep
    $(OBJECTDUMP) -d -M intel -S $@
    @mv -f $*.dep $*.dep.tmp
    @sed -e 's|.*:|$*.o:|' < $*.dep.tmp > $*.dep
    @sed -e 's/.*://' -e 's/\$$//' < $*.dep.tmp | fmt -1 | \
      sed -e 's/^ *//' -e 's/$$/:/' >> $*.dep
    @rm -f $*.dep.tmp

谁能解释一下最后 5 行代码在做什么?

$*大致对应第一行的%

  • @mv 行将旧的 basename.dep 文件移动到 basename.dep.tmp
  • 第一个 @sed 行编辑 basename.dep.tmp 中的内容,用 basename.o: 替换冒号之前的任何内容(因为 $*make, 而不是 shell).
  • 第二行 @sed 和下一行进行更多编辑 — 将 basename.dep.tmp 文件的另一个变体附加到 basename.dep.
  • 的末尾
  • @rm 行删除临时 basename.dep.tmp 文件。

要对第二个 sed 序列进行更彻底的分析,需要更详细地了解 .dep 文件中的内容以及 fmt -1 为您所做的事情。

但是,目标似乎是根据来自编译器的信息并以适合程序员的方式对其进行处理来更新适用于源文件的依赖项。我不清楚为什么。

这些行的目的是解决依赖关系处理问题。

假设您有一个 header 文件 bar.h 和一个包含行

的源文件 foo.c
#include "bar.h"

现在生成依赖文件:

$(CC) -MM $*.c > $*.dep

文件 foo.dep 现在包含:

foo.o: foo.cc bar.h

太棒了。我确定 makefile 中有一行 -include *.dep,所以现在 Make 将正确处理 foo 的依赖项。但现在假设您编辑 foo.c,删除 #include 行,并删除 no-longer-needed bar.h。下次你尝试 make foo 时,Make 将读取旧的 foo.dep 调用 bar.h,发现没有这样的 header 并且没有已知的构建它的方法,并中止。在重建 dep 文件之前,Make 不会知道 header 是不需要的,但它不能这样做,因为 header 丢失并且 Make 认为它是需要的。

一个解决方案是在出现这种情况时删除 foo.dep(如果可能的话,在 Make 中止之前)。另一种是在foo.dep中添加一行:

bar.h:

这将减轻 Make 对失踪 header 的恐惧。第一种方法需要人工注意,第二种方法可以自动化:

@mv -f $*.dep $*.dep.tmp # rename foo.dep -> foo.dep.tmp
@sed -e 's|.*:|$*.o:|' < $*.dep.tmp > $*.dep # this does nothing and appears to be vestigal
@sed -e 's/.*://' \ # remove the target, leaving foo.c bar.h
  -e 's/\$$//' \  # remove line continuation marks, if any
  < $*.dep.tmp | fmt -1 | \ # put each word on its own line
  sed -e 's/^ *//' \ # remove leading whitespace
  -e 's/$$/:/' \ # add a colon to the end of each line (making it a rule)
  >> $*.dep # save the result as foo.dep
@rm -f $*.dep.tmp  # delete the temporary file