一. build定义:



s

cripts/Kbuild.include 
 
 
 
build 
   := -f 
   $(if $(KBUILD_SRC),$(srctree)/) 
  scripts/Makefile.build obj
 
 

 
 

   $(KBUILD_SRC)常规情况下为空,所以的变量定义可简化为: 
 
 
 
build 
   := -f 
  scripts/Makefile.build obj




二. (MAKE) $(build)=的处理过程


build使用的一般形式为:


$(MAKE) $(build)= build_dir  [ argv]


斜体字部分为可变目录和参数,其中[ argv] 可选。使用scripts/Kbuild.include中的$(build)变量定义,进行变量替换后,上述命令则为:


$(MAKE) -f scripts/Makefile.build obj= build_dir  [ argv]


Make进入由参数-f指定的Make文件scripts/Makefile.build,并传入参数obj= build_dir argv。


在scripts/Makefile.build的处理过程中,传入的参数$(obj) 代表此次Make命令要处理(编译、链接、和生成) 文件所在的目录,该目录下通常情况下都会存在的Makefile文件会被Makefile.build包含。$(obj)目录下的Makefile记为$(obj)/Makefile。针对Make命令,有两种情况:不指明Make目标和指定目标。


1.不指定目标


$(MAKE) $(build)= build_dir  [ argv]


中,当没有参数[argv]时,该Make命令没有指定目标。如顶层Makefile中,$(vmlinux-dirs)的构建规则:


$(vmlinux-dirs): prepare scripts 

 

       $(Q)$(MAKE) $(build)=$@


其他的还有主机程序fixdep的构建规则:


scripts_basic: 

 

      $(Q)$(MAKE) $(build)=scripts/basic


这时会使用Makefile.build中的默认目标__build。然后更进一步,会使用$(obj)/Makefile中定义的变量来进行目标匹配。


__build在Makefile.build中的构建规则为: 

 
__build 
 : 
 $(if $(KBUILD_BUILTIN),$(builtin-target) $(lib-target) $(extra-y)) 
 \
 
     
 $(if $(KBUILD_MODULES),$(obj-m) $(modorder-target)) 
 \
 
     
 $(subdir-ym) 
 $(always)
 
    @:


首先会构建该默认目标__build的依赖。Make会寻找重建这些依赖的规则。而这些规则要么在当前的Makefile文件Makefile.build中,要么在Makefile.build include的$(obj)/Makefile中。在此不指定Make目标的情况下,会使用Makefile.build中的构建规则来重建依赖。相应地,只重构那些在$(obj)/Makefile定义的依赖。其他的依赖要么


不满足条件,要么找不到重构规则而被忽略。


例如上述$(vmlinux-dirs)规则:


$(vmlinux-dirs): prepare scripts 

 

       $(Q)$(MAKE) $(build)=$@


的构建中,没有指明Make目标,那么将使用Makefile.build中的默认目标__build,且会包含上述多目标$(vmlinux-dirs)中,实际处理时的某单一目标(此为目录)下的Makefile文件,即$(obj)/Makefile。在__build规则中,因$(KBUILD_BUILTIN)被主目录设置为1,且export,所以将首先重建依赖$(builtin-target)。而依赖$(builtin-target)的重建规则在Makefile.build中,即:


$(builtin-target) 
 : 
 $(obj-y) 
 FORCE   #### 
 $(obj)/built-in.o,且先要构建依赖$(obj-y)
 
     
  $(call if_changed,link_o_target)



该规则同样要首先重建依赖$(obj-y)。而$(obj-y)在$(obj)/Makefile中定义且被赋值。这时Make又会查找$(obj-y)包含文件的构建规则。同样地,该规则要么在Makefile.build中,要么在$(obj)/Makefile中。此处$(obj-y)为.o文件的合集,.o文件的构建规则在Makefile.build中被定义:



$(obj) 
  /%.o 
  : 
  $(src) 
  /%.c 
  $(recordmcount_source) 
  FORCE  ## 
  $(obj-y)匹配规则
 
 
     
  $(call cmd,force_checksrc)
 
 
     
  $(call if_changed_rule,cc_o_c)



就是重复这样一个递归的“规则----> 规则目标-->依赖--->重建依赖--->规则---->”....的过程,直至最后的目标文件被构建,然后逆推,由依赖层层重建其规则目标。如果构建的最终目标是主机程序,如上述fixdep的构建规则 :


scripts_basic: 

 

      $(Q)$(MAKE) $(build)=scripts/basic 

 

  Makefile.build除了要inclue $(obj)/Makefile即scripts/basic/Makefile文件外,还会include scripts/Makefile.host,在Makefile.build 对包含scripts/Makefile.host的处理如下: 

 
ifneq ( 
 $(hostprogs-y)$(hostprogs-m) 
 ,)
 
include scripts/Makefile.host    
 #编译主机程序时,要包含Makefile.host文件
 
endif



因为在此之前已经包含了scripts/basic/Makefile,且在该Makefile文件里,hostprogs-y被赋值为fixdep,那么上述ifneq分支为真。即会包含scripts/Makefile.host。



在scripts/basic/Makefile里,有如下语句:



always        := $(hostprogs-y)



那么回到不指定目标的make命令里,接下来在Makefile.build中的默认目标__build中,会匹配到重建的依赖always。注意这里变量$(always)的值为fixdep。由此触发依赖fixdep的重建(否则,就没有入口目标的依赖层层重建至fixdep)。而它的重建规则在上面包含的scripts/Makefile.host中。其余过程在此略去,详细过程可参照文档“编译产生主机文件(host-cpp)”。



总结:



由于没有指定Make目标,那么将使用Makefile.build的默认目标__build,建构的入口点就在此。Make在Makefile.build 和$(obj)/Makefile 中寻找 __build依赖的重建规则,主机程序目标还用到了Makefile.host文件。依次变量展开,依赖层层递归重建。





2.指定目标:


  一般情况下,在(MAKE) $(build)= build_dir  [ argv] 中,通过参数[ argv]  指定Make目标时,使用的是$(obj)/Makefile文件中构建规则。这时,在$(obj)/Makefile文件中不仅要给一些变量赋值,且还包含本目录下目标的重建规则。


 如:


%config 
 : scripts_basic outputmakefile FORCE
 
     
 $(Q) 
 mkdir -p include/linux include/config
 
     
  $(Q)$(MAKE) 
  $(build) 
  =scripts/kconfig $@


在此指定Make目标为自动化变量$@,当我们输入类似如下的命令:



make nitrogen6x_defconfig



那么,上述Make命令会被大致替换为:



make -f scripts/Makefile.build obj=scripts/kconfig nitrogen6x_defconfig



即指定Make的目标为nitrogen6x_defconfig。那么在$(obj)目录scripts/kconfig下的Makefile中包含nitrogen6x_defconfig模式匹配规则。其他的流程和上节的"不指定目标"处理类似。在此不再敖述。



二. 入口处:


1.顶层Makefile---- 指定目标-----include scripts/kconfig/Makefile


如在终端中执行配置命令make nitrogen6x_defconfig


%config 
 : scripts_basic outputmakefile FORCE
 
     
 $(Q) 
 mkdir -p include/linux include/config
 
     
  $(Q)$(MAKE) 
  $(build) 
  =scripts/kconfig $@





2.auto.conf autoconf.h auto.conf.cmd的生成----指定目标-----include scripts/kconfig/Makefile



include/config/%.conf 
  : 
  $(KCONFIG_CONFIG) 
  include/config/auto.conf.cmd
 
 
     
   $(Q)$(MAKE) 
   -f 
   $(srctree) 
   /Makefile silentoldconfig






将在顶层Makefile中递归到上述1中的%config规则,所以,其最终还会包含 scripts/kconfig/Makefile






3. 目标编译和链接----不指定目标-----include 各个build目标下的Makefile



$(vmlinux-dirs) 
   : prepare scripts
 
  
        
     $(Q)$(MAKE) 
    $(build) 
    =$@






4. 模块----模块建构中单独讨论


$(module-dirs) 
    :crmodverdir 
    $(objtree) 
    /Module.symvers
 
   
     
    $(Q)$(MAKE) 
    $(build) 
    = 
    $(patsubst _module_%,%,$@)
 
   
 
    
 
   
modules 
    : 
    $(module-dirs)
 
   
    @ 
    $(kecho) 
    '  Building modules, stage 2.';
 
   
     
     $(Q)$(MAKE) 
     -f 
     $(srctree) 
     /scripts/Makefile.modpost

5. 单目标----不指定目标




6. 子目录递归----不指定目标-----include递归的子目录下Makefile

scripts/Makefile.build 
    
 
   
$(subdir-ym) 
    :
 
   
     
     $(Q)$(MAKE) 
     $(build) 
     =$@





-----------------------------------------------------------------------------



三. Makefile.build文件总框架:


src 
      := 
      $(obj)
 
     

 
     
-include include/config/auto.conf  #if xxx_CONFIG配置选项
 
     
include scripts/Kbuild.include    #if_changed等变量
 
     

 
     
########################## 
      包含obj目录下的Makefile文件 
      ############################
 
     
kbuild-dir 
      := 
      $(if $(filter /%,$(src)),$(src),$(srctree)/$(src))
 
     
kbuild-file 
      := 
      $(if $(wildcard $(kbuild-dir)/Kbuild),$(kbuild-dir)/Kbuild,$(kbuild-dir)/Makefile)
 
     
include 
       $(kbuild-file)   
 
      

 
      
############################包含Makefile.lib###################################
 
      
include scripts/Makefile.lib  
 
       

 
      
###################### 
       编译主机程序时,要包含Makefile.host文件 
       #####################
 
      
ifneq ( 
       $(hostprogs-y)$(hostprogs-m) 
       ,)
 
      
include scripts/Makefile.host   
 
      
endif
 
       

 
       
######################## 
        #### 
        定义builtin-target 
        #################################
 
       
ifneq ( 
        $(strip $(obj-y) $(obj-m) $(obj-n) $(obj-) $(subdir-m) $(lib-target)) 
        ,)
 
    
builtin-target 
     := 
     $(obj) 
     /built-in.o    
     ########
 
    
endif
 
     
 
      
 
     
######################## 
      #### 
      __build构建规则#################################
 
    
__build 
     : 
     $(if $(KBUILD_BUILTIN),$(builtin-target) $(lib-target) $(extra-y)) 
     \
 
    
     
     $(if $(KBUILD_MODULES),$(obj-m) $(modorder-target)) 
     \
 
    
     
     $(subdir-ym) 
     $(always)
 
    
    @:
 
     

 
     
################### 
      $(obj)/built-in.o,且先要构建依赖$(obj-y) 
      #####################
 
     
$(builtin-target) 
      : 
      $(obj-y) 
      FORCE   
 
     
     
       $(call if_changed,link_o_target)
 
      

 
      
############################ 普通模式匹配规则#################################
 
     
define rule_cc_o_c
 
     
     
      $(call echo-cmd,checksrc) 
      $(cmd_checksrc) 
                 \
 
     
     
      $(call echo-cmd,cc_o_c) 
      $(cmd_cc_o_c) 
      ;              \
 
     
     
      $(cmd_modversions) 
                             \
 
     
     
      $(call echo-cmd,record_mcount) 
                        \
 
     
     
      $(cmd_record_mcount) 
                           \
 
     
    scripts/basic/fixdep 
      $(depfile) 
      $@ ' 
      $(call make-cmd,cc_o_c) 
      ' >    \
 
     
                                                  
      $(dot-target) 
      .tmp;  \
 
     
    rm -f 
      $(depfile) 
      ;                     \
 
     
    mv -f 
      $(dot-target) 
      .tmp 
      $(dot-target) 
      .cmd
 
     
endef
 
     
 
      
 
     
$(obj) 
      /%.o 
      : 
      $(src) 
      /%.c 
      $(recordmcount_source) 
      FORCE  ## 
      $(obj-y)匹配规则
 
     
     
      $(call cmd,force_checksrc)
 
     
     
      $(call if_changed_rule,cc_o_c)