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_basic、 outputmakefile 和 FORCE,“%config”真正有意义的依赖就只有 scripts_basic,scripts_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 为 1,KBUILD_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
字节的“头”,这个头信息描述了该镜像文件的类型、加载位置、生成时间、大小等信息。

浙公网安备 33010602011771号