u-boot makefile 中 .depend 文件生成

已知自动生成依赖的规则在顶层目录的rules.mk文件里面约定:
rules.mk:
---------
#########################################################################

_depend: $(obj).depend

$(obj).depend: $(src)Makefile $(TOPDIR)/config.mk $(SRCS)
  @rm -f $@
  @for f in $(SRCS); do /
   g=`basename $$f | sed -e 's//(.*/)/./w//1.o/'`; /
   $(CC) -M $(HOST_CFLAGS) $(CPPFLAGS) -MQ $(obj)$$g $$f >> $@ ; /
  done

#########################################################################
---------

在大多数子目录中,子目录的Makefile文件中都包含上述规则来自动生成依赖。我们以
u-boot/board/smdk2410 为例:
# cd /u-boot/board/smdk2410
[root@localhost smdk2410]# ls
config.mk  flash.c  lowlevel_init.S  Makefile  smdk2410.c  u-boot.lds
[root@localhost smdk2410]# vim Makefile
Makefile:
---------
include $(TOPDIR)/config.mk

LIB     = $(obj)lib$(BOARD).a

COBJS   := smdk2410.o flash.o
SOBJS   := lowlevel_init.o

SRCS    := $(SOBJS:.o=.S) $(COBJS:.o=.c)
OBJS    := $(addprefix $(obj),$(COBJS))
SOBJS   := $(addprefix $(obj),$(SOBJS))

$(LIB): $(obj).depend $(OBJS) $(SOBJS)
        $(AR) $(ARFLAGS) $@ $(OBJS) $(SOBJS)

clean:
        rm -f $(SOBJS) $(OBJS)

distclean:      clean                                                                                                                                        
        rm -f $(LIB) core *.bak .depend

#########################################################################

# defines $(obj).depend target
include $(SRCTREE)/rules.mk

sinclude $(obj).depend

#########################################################################
---------

已知:

$(obj)实际上为空,所以上面任何文件加上这个前缀实际上都没有用,表示在当前目录下面。 
$(TOPDIR) ==  $(SRCTREE) 就是u-boot顶层目录。

现在开始看这个Makefile,可知其终极目标为 LIB即$(obj)lib$(BOARD).a即libsmdk2410.a
而$(LIB)分别依赖于.depend,$(OBJS),$(SOBJS)

当make按规则去生成$(LIB)时,它首先要去查看.depend文件,初次make的时候,.depend文件
还没有生成,所以make下一步就会查找.depend的生产规则并生成一个.depend文件。乍一看
Makefile好像没有.depend这个次级目标,但是别急,关键在于:

include $(SRCTREE)/rules.mk   
                                                                          
这句相当于把rules.mk原方不动的展开,并插入在自己的位置上。

我们再回头看看rules.mk文件,可以发现该文件有.depend目标。
所以.../smdk2410目录下面的Makefile在make的驱动下,会按照rules.mk里面约定的规则生成
.depend文件,并把该文件放入.../smdk2410目录。

再次贴上rules.mk:
---------
$(obj).depend: $(src)Makefile $(TOPDIR)/config.mk $(SRCS)
@rm -f $@
@for f in $(SRCS); do /
g=`basename $$f | sed -e 's//(.*/)/./w//1.o/'`; /

$(CC) -M $(HOST_CFLAGS) $(CPPFLAGS) -MQ $(obj)$$g $$f >> $@ ; /
done
---------

其中.depend的依赖$(src)Makefile,$(TOPDIR)/config.mk的作用对于研究自动生成依赖的
这个问题意义并不重要,只是导入$(HOST_CFLAGS),$(CPPFLAGS)这些变量(我暂时说服自己)。
关键看$(SRCS),在这个地方$(SRCS)代表着当前目录下的源文件,包括:
flash.c  lowlevel_init.S  smdk2410.c

.depend文件的生成规则为一个for循环,也就是找出上述各个源文件的依赖关系并放入
.depend文件。

_depend: $(obj).depend

$(obj).depend: $(src)Makefile $(TOPDIR)/config.mk $(SRCS) $(HOSTSRCS)    //描述.depend 的依赖关系
  @rm -f $@                                                                                                     //强制删掉所有的目标文件,即*.depend文件
  @touch $@                                                                                                   //强制更新目标文件属性,以便使文件过期  
  @for f in $(SRCS); do /                                                                                  //for循环读取子目录下的文件
   g=`basename $$f | sed -e 's//(.*/)/./w//1.o/'`; /                                       

//这一段比较难懂,我们把它分开来看,“basename $$f” 代表去变量$f的文件名,去掉路径等信息。“$f”为SRCS目录下的具体文  

//件。“|”为管道描述,“sed -e 's//(.*/)/./w//1.o/'`”为一个sed命令的文本处理部分,”-e“ 命令行,"s/.../.."为替换命令,

//“/(.*/)/./w”代表匹配任意除换行符开始的任意长度的字符接着是”.“字符最后是一个匹配字母或数字或下划线或汉字,"//1.O/" /1为前

//面的.*/匹配字符串 ,".O"加上.o。简单的说,此句实现的功能为将一个源文件替换为一个.o的OBJ文件,e.g..将一个.c的问题变成.o文件.

//对于这一部分如果仍然不是很清楚,可以看一下正则表达式文档。。。

   $(CC) -M $(CPPFLAGS) -MQ $(obj)$$g $$f >> $@ ; /

//产生依靠文件
  done
  @for f in $(HOSTSRCS); do /
   g=`basename $$f | sed -e 's//(.*/)/./w//1.o/'`; /
   $(HOSTCC) -M $(HOSTCPPFLAGS) -MQ $(obj)$$g $$f >> $@ ; /
  done


生成的.depend 文件的内容如下(给出概略形式):

.depend  
---------
flash.o:  flash.c xxx.h xxx.h ...
smdk2410.o:  smdk2410.c xxx.h xxx.h ...
lowlevel_init.o:  lowlevel_init.s xxx.h xxx.h ...
---------

我们再回到.../smdk2410下面的Makefile,看终极目标$(LIB)的另外两个依赖:
$(OBJS),$(SOBJS) 也就是flash.o ,smdk2410.o 和 lowlevel_init.o

似乎我们在.../smdk2410下面的Makefile里面看不到上述目标,但是不要急,看看该Makefile的
最后一行:sinclude $(obj).depend
也就是说把flash.o ,smdk2410.o 和 lowlevel_init.o的依赖关系包含过去了.

通过上述分析,我们知道终极目标$(LIB)的所有依赖关系及次级目标都理清楚了,Make命令最终
可以递归的把$(LIB)生成。

之所以称为"自动生成依赖",我们可以看到:flash.o ,smdk2410.o 和 lowlevel_init.o的依赖
关系都是make自己来完成的,不需要我们手动改写。即使我们的某个源文件的依赖关系发生了变
化,则.depend文件的时间戳会比某个源文件的时间戳早,则make会重新生成.depend文件!这样
就减轻了繁琐的人工劳动。

最后,我们再来一个超级简单的例子:
=========

[root@localhost maketest]# ls -a
.  ..  app.c  Makefile  print.c  print.h  rules.mk

app.c:
---------
int main()
{
    PrintStr("Hello world !");
 return 0;
}

---------

print.h:
---------
void PrintStr(char *);

---------

print.c:
---------
#include<stdio.h>
#include"print.h"
void PrintStr(char *s)
{
 puts(s);
 return;
}

---------

Makefile:
---------
OBJS   := app.o print.o
SRCS    := $(OBJS:.o=.c)

Tar: .depend $(OBJS) 
        gcc -o $@ $(OBJS)

clean:
        rm -f  $(OBJS)

include rules.mk
sinclude .depend
---------

rules.mk:
---------
.depend:   $(SRCS)
  @rm -f $@
  @for f in $(SRCS); do /
   g=`basename $$f | sed -e 's//(.*/)/./w//1.o/'`; /
   $(CC) -MM  -MQ  $$g $$f >> $@ ; /
  done
---------

make之后:
[root@localhost maketest]# ls -a
.  ..  app.c  app.o  .depend  Makefile  print.c  print.h  print.o  rules.mk  Tar

[root@localhost maketest]# cat .depend
app.o: app.c
print.o: print.c print.h

你可能感兴趣的:(正则表达式,gcc,vim,文档,include,makefile)