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中的规则编译。

  

原文地址:https://www.cnblogs.com/genshu123/p/11198790.html