嵌入式linux之顶层makefile解析
内核顶层目录make过程
简易描述一下整个编译过程
执行make XXX_defconfige,最终目的会生成.config,.config里面回有很多配置项,
主要用来选择架构和加入哪些模块进行编译
执行make
首先,主要目标先生成vmlinux,在利用vmlinux生成Image ,zImage 、uImage等镜像烧写文件
all: vmlinux
依赖项vmlinux
继续研究vmlinux
vmlinux: scripts/link-vmlinux.sh $(vmlinux-deps) FORCE
依赖项scripts/link-vmlinux.sh和vmlinux-deps
先说一下vmlinux-deps
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/arm/kernel/vmlinux.lds
继续深入解开可得:
head-y = arch/arm/kernel/head.o
init-y = init/built-in.o
drivers-y = drivers/built-in.o sound/built-in.o firmware/built-in.o
net-y = net/built-in.o
libs-y = arch/arm/lib/lib.a lib/lib.a arch/arm/lib/built-in.o lib/built-in.o
core-y = 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
最终可得:
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
在各个目录下面获取built-in.o文件,其实还有些生成了.a,然后利用arch/arm/kernel/vmlinux.lds和scripts/link-vmlinux.sh 这个脚本来链接出 vmlinux打包生成vmlinux
那么这些built-in.o是如何生成得呢
顶层makefile中有如下代码:
$(sort $(vmlinux-deps)): $(vmlinux-dirs) ;
意思是把vmlinux-deps按照字母排序,也就是把上面得built-in.o 得目录进行排序,而这些built-in.o得依赖项是 $(vmlinux-dirs)
追踪代码可得
vmlinux-dirs := $(patsubst %/,%,$(filter %/, $(init-y) $(init-m) \
$(core-y) $(core-m) $(drivers-y) $(drivers-m) \
$(net-y) $(net-m) $(libs-y) $(libs-m) $(virt-y)))
解开可得
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
另外还有
$(vmlinux-dirs): prepare scripts
$(Q)$(MAKE) $(build)=$@
上下得目标进行合并,最后通过 $(Q)$(MAKE) $(build)=$@这条命令来生成vmlinux-dirs所敞开得这些目录里面得built-in.o
分析命令
$(Q)$(MAKE) $(build)=$@
命令敞开
@ make -f ./scripts/Makefile.build obj=$@
根据目标继续敞开
@ make -f ./scripts/Makefile.build obj=init
@ make -f ./scripts/Makefile.build obj=usr
@ make -f ./scripts/Makefile.build obj=arch/arm/vfp
@ make -f ./scripts/Makefile.build obj=arch/arm/vdso
@ make -f ./scripts/Makefile.build obj=arch/arm/kernel
@ make -f ./scripts/Makefile.build obj=arch/arm/mm
@ make -f ./scripts/Makefile.build obj=arch/arm/common
@ make -f ./scripts/Makefile.build obj=arch/arm/probes
@ make -f ./scripts/Makefile.build obj=arch/arm/net
@ make -f ./scripts/Makefile.build obj=arch/arm/crypto
@ make -f ./scripts/Makefile.build obj=arch/arm/firmware
@ make -f ./scripts/Makefile.build obj=arch/arm/mach-imx
@ make -f ./scripts/Makefile.build obj=kernel
@ make -f ./scripts/Makefile.build obj=mm
@ make -f ./scripts/Makefile.build obj=fs
@ make -f ./scripts/Makefile.build obj=ipc
@ make -f ./scripts/Makefile.build obj=security
@ make -f ./scripts/Makefile.build obj=crypto
@ make -f ./scripts/Makefile.build obj=block
@ make -f ./scripts/Makefile.build obj=drivers
@ make -f ./scripts/Makefile.build obj=sound
@ make -f ./scripts/Makefile.build obj=firmware
@ make -f ./scripts/Makefile.build obj=net
@ make -f ./scripts/Makefile.build obj=arch/arm/lib
@ make -f ./scripts/Makefile.build obj=lib
直接说一下结果,这条命令得意思就是说make 到每个obj所指向得目录里面去编译/scripts/Makefile,而scripts/Makefile会把
每个目录里面得makefile给include进去,而每个目录里面得makefile会把目录下面得所有文件用如下得形式进行一个定义,例如
obj-$(CONFIG_GPIO_MOXART) += gpio-moxart.o
obj-$(CONFIG_GPIO_MPC5200) += gpio-mpc5200.o
obj-$(CONFIG_GPIO_MPC8XXX) += gpio-mpc8xxx.o
obj-$(CONFIG_GPIO_MSIC) += gpio-msic.o
obj-$(CONFIG_GPIO_MVEBU) += gpio-mvebu.o
obj-$(CONFIG_GPIO_MXC) += gpio-mxc.o
obj-$(CONFIG_GPIO_MXS) += gpio-mxs.o
obj-$(CONFIG_GPIO_OCTEONy) += gpio-octeon.o
其中$()里面得配置项就行.config里面得定义选项,当被复制成y得时候,就相当于是obj-y,这时候模块会被加入编译
例如obj-$(CONFIG_GPIO_MXC) += gpio-mxc.o,CONFIG_GPIO_MXC被定义成y,则
obj-y += gpio-mxc.o,对应得gpio-mxc.o会被加入编译,最终生成built-in.o
然后顶层目录在去把这些built-in.o 链接成vmlinux
后面得镜像文件Image ,zImage 、uImage都是用vmlinux生成得
顶层makefile 代码如下
BOOT_TARGETS = zImage Image xipImage bootpImage uImage
$(BOOT_TARGETS): vmlinux 目标:依赖项
$(Q)$(MAKE) $(build)=$(boot) MACHINE=$(MACHINE) $(boot)/$@
解开命令得
@ make -f ./scripts/Makefile.build obj=arch/arm/boot MACHINE=arch/arm/boot/zImage
@ make -f ./scripts/Makefile.build obj=arch/arm/boot MACHINE=arch/arm/boot/Image
@ make -f ./scripts/Makefile.build obj=arch/arm/boot MACHINE=arch/arm/boot/xipImage
@ make -f ./scripts/Makefile.build obj=arch/arm/boot MACHINE=arch/arm/boot/bootpImage
@ make -f ./scripts/Makefile.build obj=arch/arm/boot MACHINE=arch/arm/boot/uImage
也是利用./scripts/Makefile.build这个脚本去链接生成