linux内核顶层Makefile

  Linux 的顶层 Makefile uboot 的顶层 Makefile 非常相似,因为 uboot 参考了 Linux,前 600行几乎一样。


1.make ***_defconfig配置内核

config: scripts_basic outputmakefile FORCE
    $(Q)$(MAKE) $(build)=scripts/kconfig $@
%config: scripts_basic outputmakefile FORCE
    $(Q)$(MAKE) $(build)=scripts/kconfig $@

make xxx_defconfig”与目标“%config”匹配,因此执行。“%config”依赖scripts_basicoutputmakefile FORCE,“%config”真正有意义的依赖就只有 scripts_basicscripts_basic 的规则如下

scripts_basic:
    $(Q)$(MAKE) $(build)=scripts/basic
    $(Q)rm -f .tmp_quiet_recordmcount

build定义在文件scripts/Kbuild.include中,

build := -f $(srctree)/scripts/Makefile.build obj

因此,scripts_basic展开就是:

@make -f ./scripts/Makefile.build obj=scripts/basic
@rm -f . tmp_quiet_recordmcount

不要忘了%config: scripts_basic outputmakefile FORCE后面还有:$(Q)$(MAKE) $(build)=scripts/kconfig $@

所以make xxx_defconfig 就会执行

@make -f ./scripts/Makefile.build obj=scripts/basic
@make -f ./scripts/Makefile.build obj=scripts/kconfig xxx_defconfig

(1)scripts/basic

  scripts_basic 目标对应的命令为: @make -f ./scripts/Makefile.build obj=scripts/basic。打开文件 scripts/Makefile.build,有如下代码

# The filename Kbuild has precedence over Makefile
kbuild-dir := $(if $(filter /%,$(src)),$(src),$(srctree)/$(src))
kbuild-file := $(if $(wildcard $(kbuild-dir)/Kbuild),$(kbuilddir)/Kbuild,$(kbuild-dir)/Makefile)
include $(kbuild-file)

kbuild-dir 展开后为:

kbuild-dir=./scripts/basic

kbuild-file 展开后为:

kbuild-file= ./scripts/basic/Makefile

最后展开:

include ./scripts/basic/Makefile 

scripts/Makefile.build中

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

__build 是默认目标,因为命令“@make -f ./scripts/Makefile.build obj=scripts/basic”没有指定目标,所以会使用到默认目标__build。在顶层 Makefile 中, KBUILD_BUILTIN 1KBUILD_MODULES 为空,因此展开后目标__build 为 :

__build:$(builtin-target) $(lib-target) $(extra-y)) $(subdir-ym) $(always)
@:

其中

builtin-target =
lib-target =
extra-y =
subdir-ym =
always = scripts/basic/fixdep scripts/basic/bin2c

  __build 依赖于 scripts/basic/fixdep scripts/basic/bin2c,所以要先将 scripts/basic/fixdep scripts/basic/bin2c.c 这两个文件编译成 fixdep bin2c
综上所述, scripts_basic 目标的作用就是编译出 scripts/basic/fixdep scripts/basic/bin2c 这两个软件。

(2)scripts/kconfig xxx_defconfig

@make -f ./scripts/Makefile.build obj=scripts/kconfigxxx_defconfig

src= scripts/kconfig
kbuild-dir = ./scripts/kconfig
kbuild-file = ./scripts/kconfig/Makefile
include ./scripts/kconfig/Makefile

Makefile.build 会读取 scripts/kconfig/Makefile 中的内容

%_defconfig: $(obj)/conf
    $(Q)$< $(silent) --defconfig=arch/$(SRCARCH)/configs/$@
$(Kconfig)

xxx_defconfig 匹配,展开后

%_defconfig: scripts/kconfig/conf
    @ scripts/kconfig/conf --defconfig=arch/arm/configs/%_defconfig Kconfig

  %_defconfig依赖scripts/kconfig/conf,所以会编译scripts/kconfig/conf.c生成conf这个软件。此软件就会将%_defconfig 中的配置输出到.config 文件中,最终生成 Linux kernel 根目录下的.config 文件。 

 

2.make

  将所有的目录的.c文件编译成built-in.o或.a文件,最后链接生成ELF的vmlinux,链接脚本为 arch/arm/kernel/vmlinux.lds,链接过程是由shell脚本scripts/link-vmlinux.s来完成的

_all:all

all:vmlinux

vmlinux: scripts/link-vmlinux.sh $(vmlinux-deps) FORCE


vmlinux-deps= $(KBUILD_LDS) $(KBUILD_VMLINUX_INIT) $(KBUILD_VMLINUX_MAIN)
KBUILD_VMLINUX_INIT= $(head-y) $(init-y)
KBUILD_VMLINUX_MAIN = $(core-y) $(libs-y) $(drivers-y) $(net-y)
KBUILD_LDS= arch/$(SRCARCH)/kernel/vmlinux.lds,其中 SRCARCH=arm,因此 KBUILD_LDS= arch/arm/kernel/vmlinux.lds

综上所述, vmlinux 的依赖为: scripts/link-vmlinux.sh$(head-y) $(init-y)$(core-y) $(libs-y) $(drivers-y) $(net-y)arch/arm/kernel/vmlinux.lds FORCE
  省略scripts/link-vmlinux.sh、 $(head-y) 、 $(init-y)、 $(core-y) $(libs-y) 、 $(drivers-y) 、 $(net-y)、 arch/arm/kernel/vmlinux.lds。
最后built-in.o或.a文件,最后链接生成ELF的vmlinux

 

3.make zImage

  vmlinux是ELF格式文件,是最原始的内核文件,Image是使用objcopy取消一些vmlinux中一些信息(符号表),zImage是Image经过gzip压缩过。uImage 是老版本 uboot 专用的镜像文件, uImag 是在 zImage 前面加了一个长度为 64
字节的“头”,这个头信息描述了该镜像文件的类型、加载位置、生成时间、大小等信息。

posted @ 2020-12-04 10:25  11YS  阅读(296)  评论(0)    收藏  举报