linux內核Makefile中的build構建機制

一. build定義:
scripts/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. 單目標----不指定目標
%.o:%.c prepare scripts FORCE
    $(Q)$(MAKE)$(build)=$(build-dir)$(target-dir)$(notdir $@)

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)
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章