之前的文章分析了 Linux内核源码的 make过程。顶层 Makefile会编译 目标 _all,经过上一篇文章的分析,目标_all 最终依赖于 vmlinux。
vmlinux-deps= $(KBUILD_LDS) $(KBUILD_VMLINUX_INIT) $(KBUILD_VMLINUX_MAIN)
- vmlinux-deps = arch/arm/kernel/vmlinux.lds arch/arm/kernel/head.o \
- init/built-in.o usr/built-in.o \
- arch/arm/vfp/built-in.o arch/arm/vdso/built-in.o \
- arch/arm/kernel/built-in.o arch/arm/mm/built-in.o \
- arch/arm/common/built-in.o arch/arm/probes/built-in.o \
- arch/arm/net/built-in.o arch/arm/crypto/built-in.o \
- arch/arm/firmware/built-in.o arch/arm/mach-imx/built-in.o \
- kernel/built-in.o mm/built-in.o \
- fs/built-in.o ipc/built-in.o \
- security/built-in.o crypto/built-in.o\
- block/built-in.o arch/arm/lib/lib.a\
- lib/lib.a arch/arm/lib/built-in.o\
- lib/built-in.o drivers/built-in.o \
- sound/built-in.o firmware/built-in.o \
- net/built-in.o
937 $(sort $(vmlinux-deps)): $(vmlinux-dirs) ;
- 889 vmlinux-dirs := $(patsubst %/,%,$(filter %/, $(init-y) $(init-m) \
- 890 $(core-y) $(core-m) $(drivers-y) $(drivers-m) \
- 891 $(net-y) $(net-m) $(libs-y) $(libs-m)))
- vmlinux-dirs = init usr arch/arm/vfp \
- arch/arm/vdso arch/arm/kernel arch/arm/mm \
- arch/arm/common arch/arm/probes arch/arm/net \
- arch/arm/crypto arch/arm/firmware arch/arm/mach-imx\
- kernel mm fs \
- ipc security crypto \
- block drivers sound \
- firmware net arch/arm/lib \
- lib
- 946 $(vmlinux-dirs): prepare scripts
- 947 $(Q)$(MAKE) $(build)=$@
目标 vmlinux-dirs 依赖 prepare 和 scripts,这两个依赖不去浪费时间了。
重点看一下第 947 行的命令。build 前面已经说了,值为“-f ./scripts/Makefile.build obj”,
因此,第 947 行的命令展开就是:
@ make -f ./scripts/Makefile.build obj=$@
“@ make -f ./scripts/Makefile.build obj=init”
这里又要用到 Makefile.build 这个脚本了,此脚本默 认目标为__build,
我们再来看一下,__build 目标对应的规则如 下:
- 94 __build: $(if $(KBUILD_BUILTIN),$(builtin-target) $(lib-target)
- $(extra-y)) \
- 95 $(if $(KBUILD_MODULES),$(obj-m) $(modorder-target)) \
- 96 $(subdir-ym) $(always)
- 97 @:
- __build: $(builtin-target) $(lib-target) $(extra-y)) $(subdir-ym) $(always)
- @:
- 86 ifneq ($(strip $(obj-y) $(obj-m) $(obj-) $(subdir-m) $(libtarget)),)
- 87 builtin-target := $(obj)/built-in.o
- 88 endif
- 328 ifdef builtin-target
- 329 quiet_cmd_link_o_target = LD $@
- 330 # If the list of objects to link is empty, just create an empty
- built-in.o
- 331 cmd_link_o_target = $(if $(strip $(obj-y)),\
- 332 $(LD) $(ld_flags) -r -o $@ $(filter $(obj-y), $^) \
- 333 $(cmd_secanalysis),\
- 334 rm -f $@; $(AR) rcs$(KBUILD_ARFLAGS) $@)
- 335
- 336 $(builtin-target): $(obj-y) FORCE
- 337 $(call if_changed,link_o_target)
- 338
- 339 targets += $(builtin-target)
- 340 endif # builtin-target
$(call if_changed,link_o_target)
也就是调用函数 if_changed,参数为 link_o_target,其返回值就是具体的命令。前面讲过了 if_changed,它会调用 cmd_$(1)所对应的命令($(1)就是函数的第 1 个参数)。
在这里就是调用 cmd_link_o_target 所对应的命令,也就是第 331~334 行的命令。cmd_link_o_target 就是使用 LD 将某个目录下的所有 .o 文件链接在一起,最终形成 built-in.o。