Linux內核編譯make做了什么?


執行make默認目標的依賴鏈如下:

  

  1.  include/config/auto.conf去匹配include/config/%.conf,執行其命令: $(Q)$(MAKE) -f $(srctree)/Makefile silentoldconfig即make -f ./Makefile silentoldconfig, 該句執行與make x210ii_qt_defconfig相似 silentoldconfig匹配到%config,其依賴scripts_basic,生成fixdep  docproc  hash 再回到%config下執行$(Q)$(MAKE) $(build)=scripts/kconfig $@即make scripts/Makefile.build obj=scripts/kconfig silentoldconfig,其過程為Makefile.build 包含scripts/kconfig/Makefile,其包含了silentoldconfig目標,silentoldconfig又依賴於scripts/kconfig/conf, Makefile.host依據scripts/kconfig里的材料再次生成conf,回到執行silentoldconfig目標下的命令$< -s $(Kconfig) 即scripts/kconfig/conf -s arch/arm/Kconfig該命令根據.config和arch/arm/Kconfig生成include/config/auto.conf.cmd, include/config/auto.conf ,include/generated/autoconf.h

  2.  回到include/config/kernel.release,該目標命令:

  $(Q)echo "$(KERNELVERSION)$$($(CONFIG_SHELL) $(srctree)/scripts/setlocalversion $(srctree))" > $@,該句將版本信息輸出到include/config/kernel.release,

  3.  再回到prepare3,無命令;

  4.  回到prepare2,無命令,

  5.  到include/linux/version.h下執行$(call filechk,version.h)該句得到include/linux/version.h;

  6.  再到include/generated/utsrelease.h下執行$(call filechk,utsrelease.h)得到include/generated/utsrelease.h;

  7.  再回到prepare1,無命令;再到scripts_basic和上次功能一樣;回到archprepare執行$(Q)$(MAKE) $(clean)=$(boot),該句產生include/generated/mach-types.h,該命令再arch/arm/Makefile中;

  8.  回到prepare0 執行$(Q)$(MAKE) $(build)=即把當前目錄傳遞給scripts/Makefile.build,則該makefile會包含根目錄下的kbuild,根據該文件下的規則產生include/generated/bounds.h和include/generated/asm-offsets.h;

  9.  回到prepare0 執行下一句$(Q)$(MAKE) $(build)=. missing-syscalls該句根據kbuild下的規則去執行scripts/checksyscalls.sh腳本,

  10.  到scripts,開始執行scripts下的命令$(Q)$(MAKE) $(build)=$(@)  即make -f scripts/Makefile.host obj=script  先包含scripts下的Makefile默認執行目標__build其此時依賴鏈如下:

__build:

$(subdir-ym)  $(always)

subdir-ym=scripts/mod  always= scripts/kallsyms   scripts/pnmtologo   scripts/conmakehash

  開始$(subdir-ym)的命令$(Q)$(MAKE) $(build)=$@即make -f  scripts/Makefile.build obj=scripts/mod該命令先用scripts/mod/mk_elfconfig.c生成mk_elfconfig,再用mk_elfconfig生成mk_elfconfig.h,最后得到scripts/mod/modpost,

  退出回到$(always)得到scripts/kallsyms scripts/pnmtologo scripts/conmakehash退出scripts

  11.  接下來回到目標$(vmlinux-dirs)執行至關重要的一句話$(Q)$(MAKE) $(build)=$@首先我們來分析$(vmlinux-dirs)它包含  $(init-y)   $(init-m)   $(core-y)   $(core-m)   $(drivers-y)   $(drivers-m)   $(net-y)   $(net-m)   $(libs-y)   $(libs-m) 基本也就是整個內核了,打印出來為:

  vmlinux-dirs = init  usr  arch/arm/kernel  arch/arm/mm  arch/arm/common  arch/arm/mach-s5pv210  arch/arm/plat-s5p  arch/arm/plat-samsung  arch/arm/vfp  kernel  mm  fs ipc  security  crypto  block  drivers  sound  firmware  net  arch/arm/lib  lib,$(Q)$(MAKE) $(build)=$@將其一一執行。舉例:$@=init時:$(Q)$(MAKE) $(build)=$@即為make -f scripts/Makefile.build obj=init 將包含init/Makefile,其中定義了一些變量和一些規則導致__build的依賴為編入內核模式即builtin-target = init/built-in.o最后根據scripts/Makefile.build,和init/Makefile中的規則生成 init/built-in.o,執行完成退出。

  12.  最后生成$(vmlinux-lds)  vmlinux.o  $(kallsyms.o)  vmlinux,zimage

 

總結:

  生成內核的過程:先做准備工作,目標$(vmlinux-dirs)的依賴prepare的scripts用於產生頭文件的一些功能文件,接着對$(vmlinux-dirs)下文件有一一生成,最后生成$(vmlinux-lds)  vmlinux.o  $(kallsyms.o)  vmlinux,zimage

 

關於文件生成機制:

  主Makefile調用scripts/Makefile.build並且傳入obj變量指明要編譯的文件目錄,scripts/Makefile.build中會包含obj變量的makefile或者kbuild,如果執行時未傳入目標則會默認執行scripts/Makefile.build中的__build,該目標有三種依賴模式:編入模式(鏈接到內核),非編入模式,編譯子文件和主機編譯模式,每種依賴模式的確定要根據obj中Makefile定義的變量來確定,編譯規則則是按照scripts/Makefile.build,scripts/Makefile.host,scripts/Makefile.lib,obj/Makefile等來確定;如果執行時指定目標,則obj下的makefile必然有相應的目標與之對應,再根據scripts/Makefile.build,scripts/Makefile.host,scripts/Makefile.lib,obj/Makefile中的規則編譯。

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

  

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM