本文以ast2500evb板子的linux kernel编译来进行。
该板子使用的是arm cpu(1176)
编译内核的命令参数为make ARCH=arm CROSS_COMPILE=arm-linux-
首先来看顶层目录的Makefile.
Linux/Makefile
588行定义了make的target为vmlinux,但是,要注意了,我们需要明白make是怎么工作的:make程序首先读取-f参数指定的makefile文件或当前目录下的Makefile或makefile文件,并且递归读取makefile文件中的include包含的其他目录的makefile文件。当读取了所有的makefile文件后,构建编译工程,然后才开始make target的真正工作。
另外,makefile中,同名的target全部都会被执行,比如下面的例子:
我们执行make操作的输出为:
我们回到顶层makefile文件的588-596行,588行定义的target ‘all’依赖为vmlinux.
而596行include进的makefile中定义的’all’ target依赖为zImage。
我们来看一下596行所包含的makefile文件($SRCARCH=arm)。
Linux/arch/arm/Makefile
我们没有配置CONFIG_XIP_KERNEL, 故282行设置了KBUILD_IMAGE为zImage.
290行,定义了target ‘all’,依赖zImage.
所以,对于ast2500evb板子来说,make all的依赖有2个,一个是默认的vmlinux, 一个是zImage。
我们先来看第一个依赖vmlinux,这是一个原始的未压缩过的linux kernel image,zImage,bzImage之类的都是再vmlinux基础上,施以不同压缩算法而成的image.
Linux/Makefile
827行指示vmlinux依赖于scripts/link-vmlinux.sh和$(vmlinux-deps), 而$(vmlinux-deps)等于812-814行定义的。
其中,head-y定义再linux/arch/arm/Makefile, 如下:
init-y, core-y, libs-y, drivers-y, net-y等定义在linux/Makefile
他们为对应目录的built-in.o。
比如init-y为init/built-in.o.
对于core-y,libs-y以及drivers-y还有一部分定义在linux/arch/arm/Makefile中,如下:
我们回到vmlinux的依赖中,$(vmlinux-deps)这个它又有依赖:
Linux/Makefile
即$(vmlinux-deps)排序后的list又依赖$(vmlinux-dirs)
$(vmlinux-dirs)变量就是对应的目录:
Linux/Makefile
即$(vmlinux-dirs)为以下目录:
init, arch/arm/kernel, arch/arm/mm, arch/arm/common, arch/arm/net, arch/arm/crypto, arch/arm/firmware, arch/arm/mach-astevb, drivers, sound, firmware, net, lib, arch/arm/lib
这个$(vmlinux-dirs)是怎么生成呢?或者需要什么action呢?这些也定义在linux/Makefile中。
Linux/Makefile
这里,851行的build定义在linux/scripts/Kbuild.include(335行)
Linux/scripts/Kbuild.include
故linux/Makefile:851行相当于:make -f scripts/Makefile.build obj=$(vmlinux-dirs)
这个make命令的target为scripts/Makefile.build中的第一个target(__build):
scripts/Makefile.build
且src代表了$(vmlinux-dirs)
scripts/Makefile.build
这个__build依赖于$(subdir-ym),这个subdir-ym定义在scripts/Makefile.lib中(104行)
Scripts/Makefile.lib
即$(subdir-ym)就是$(obj-y)和$(obj-m)
那么这些$(obj-y)和$(obj-m)又定义在哪?
回到Makefile.build
scripts/Makefile.build
即scripts/Makefile.build中又include了$(vmlinux-dirs)定义的目录下Makefile.
比如arch/arm/kernel/Makefile
这样,就把所有代码都编译成了二进制文件了。
至于ld,在顶层Makefile中定义了使用的lds文件为arch/arm/kernel/vmlinux.lds
这个文件定义了入口函数stext:
arch/arm/kernel/vmlinux.lds
stext定义在arch/arm/kernel/head.S中.
当生成vmlinux这个image之后,我们来看其他image的生成(zImage)
Linux/arch/arm/Makefile
从上述makefile可以看处zImage Image xipImage bootpImage uImage都是依赖于vmlinux(305行),然后通过命令:
make -f scripts/Makefile.build obj=arch/arm/boot MACHINE= arch/arm/mach-astevb arch/arm/boot/zImage
这样相当于include了arch/arm/boot/Makefile
Scripts/Makefile.build
arch/arm/boot/Makefile