Makefile解释

时间:2016-09-18 21:07:23

标签: c sed makefile gnu-make

我是makefiles的新手,并试图理解一些代码:

%.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行代码在做什么吗?

2 个答案:

答案 0 :(得分:4)

这些行的目的是处理依赖性处理的问题。

假设您有一个头文件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行,并删除了不再需要的bar.h。下次尝试make foo时,Make会读取要求foo.dep的旧bar.h,看到没有这样的标题,也没有已知的方法来构建它,并中止。 Make不会知道在重建dep文件之前不需要标头,因为标头丢失而且Make认为它是必需的,所以它无法做到。

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

bar.h:

这将缓解Make对失踪标题的担忧。第一种方法需要人为关注,第二种方法可以自动化:

@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

答案 1 :(得分:3)

$*大致对应于第一行中的%

  • @mv行将旧basename.dep文件移至basename.dep.tmp
  • 第一行@sed行编辑了basename.dep.tmp中的内容,用basename.o:替换了一个冒号(因为$*make扩展,不是贝壳)。
  • 第二行@sed行和以下行进行更多编辑 - 将basename.dep.tmp文件的另一个变体附加到basename.dep的末尾。
  • @rm行会删除临时basename.dep.tmp文件。

对第二个sed序列进行更全面的分析需要更详细地了解.dep文件中的内容以及fmt -1为您做的确切内容。

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