Linux 3.6内核编译vmlinux,bzImage

Tips1:在根目录中的Makfile中include了2次目标体系结构下的Makefile文件

第一次:

481 include $(srctree)/arch/$(SRCARCH)/Makefile
482 export KBUILD_DEFCONFIG KBUILD_KCONFIG

由注释可知,此处读取具体体系结构下的Makefile是为了设置KBUILD_DEFCONFIG.用于如果make时使用参数defconfig。

556 all: vmlinux

如果在make时没有给定参数,这个all就是默认final goal。但是它会被具体体系结构下的目标覆盖。也就是说它并不是我们的终极目标。


第二次include具体体系结构下的Makefile文件

564 include $(srctree)/arch/$(SRCARCH)/Makefile

在该文件中:

150 all: bzImage
155 bzImage: vmlinux

这里关系到GNU Make的知识,如果出现了相同的target,那么后面的target将会把前面的覆盖,并且执行后面一个的依赖和命令。所以这里发生两次覆盖,首先,556行的vmlinux覆盖了在482行include中带入的bzImage,而在564include后,bzImage又作为final goal覆盖了vmlinux。回到第一次注释,那里include具体体系结构下的Makefile就是为了设置参数而已。

最终确定final goal是第二次include。它一定要在all: vmlinux之后。


ps:再看一眼155行,其实bzImage是依赖于vmlinux的。于是,接下来,tips。看看vmlinux


Tips2:vmlinux的依赖(逆着退,只看看vmlinux的直接依赖)

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

依赖:

743 vmlinux-deps := $(KBUILD_LDS) $(KBUILD_VMLINUX_INIT) $(KBUILD_VMLINUX_MAIN)

依赖:

738 export KBUILD_VMLINUX_INIT := $(head-y) $(init-y)
 739 export KBUILD_VMLINUX_MAIN := $(core-y) $(libs-y) $(drivers-y) $(net-y)
 740 export KBUILD_LDS          := arch/$(SRCARCH)/kernel/vmlinux.lds

这里使用export是为了让这些变量外部可见,给scripts/link-vmlinux.sh用的

依赖:

 729 init-y          := $(patsubst %/, %/built-in.o, $(init-y))
 730 core-y          := $(patsubst %/, %/built-in.o, $(core-y))
 731 drivers-y       := $(patsubst %/, %/built-in.o, $(drivers-y))
 732 net-y           := $(patsubst %/, %/built-in.o, $(net-y))
 733 libs-y1         := $(patsubst %/, %/lib.a, $(libs-y))
 734 libs-y2         := $(patsubst %/, %/built-in.o, $(libs-y))
 735 libs-y          := $(libs-y1) $(libs-y2)

由patsubst函数后,将init-y等内容中本来由/结尾的文件都变成了/built-in.o的文件了。

其中head-y是定义在体系结构相关的Makefile中的。在其中也对core-y,drivers-y进行了修改。

157 head-y := arch/x86/kernel/head_$(BITS).o
158 head-y += arch/x86/kernel/head$(BITS).o
159 head-y += arch/x86/kernel/head.o

对于init-y,core-y,drivers-y,libs-y依赖于:

 506 init-y          := init/
 507 drivers-y       := drivers/ sound/ firmware/
 508 net-y           := net/
 509 libs-y          := lib/
 510 core-y          := usr/

在x86/Makefile中的修改:

161 libs-y  += arch/x86/lib/
162 
163 # See arch/x86/Kbuild for content of core part of the kernel
164 core-y += arch/x86/
165 
166 # drivers-y are linked after core-y
167 drivers-$(CONFIG_MATH_EMULATION) += arch/x86/math-emu/
168 drivers-$(CONFIG_PCI)            += arch/x86/pci/
169 
170 # must be linked after kernel/
171 drivers-$(CONFIG_OPROFILE) += arch/x86/oprofile/
172 
173 # suspend and hibernation support
174 drivers-$(CONFIG_PM) += arch/x86/power/
175 
176 drivers-$(CONFIG_FB) += arch/x86/video/

小结:

vmlinux直接依赖于

(1)arch/x86/kernel/vmlinux.lds

(2)arch/x86/kernel/head32.o,arch/x86/kernel/head_32.o,arch/x86/kernel/head.o以及

init,usr,kernel,mm,fs,ipc,security,crypto,block,arch/x86,drivers,sound,firmware,net,lib,arch/x86/lib,arch/x86/oprofile,arch/x86/power,arch/x86/video目录下的/build-in.o文件,/lib.a文件

(3)以及一个shell脚本scripts/link-vmlinux.sh在kernel 2.26版本中没有该脚本,它所要完成的任务就链接起上述文件形成vmlinux)


Tips3:确定目标代码的运行平台(ARCH)。即设置SRCARCH的过程。逆向寻找

在根目录的Makefile中

200 SRCARCH         := $(ARCH)

195 ARCH            ?= $(SUBARCH)

//arch可以来自make的参数行(包括环境变量的设置),如果没有,就来自SUBARCH

 168 SUBARCH := $(shell uname -m | sed -e s/i.86/i386/ -e s/sun4u/sparc64/ \
 169                                   -e s/arm.*/arm/ -e s/sa110/arm/ \
 170                                   -e s/s390x/s390/ -e s/parisc64/parisc/ \
 171                                   -e s/ppc.*/powerpc/ -e s/mips.*/mips/ \
 172                                   -e s/sh[234].*/sh/ )

这条命令的作用,开启一个shell进程,执行uname -m命令。输出主机的硬件架构名称。再用后面的sed命令进行筛选,比如

sed -e s/i.86/i386表示,只要硬件架构是某86,都给它叫做i386.

所以SRCARCH在200行之前就确定了。看下tip1中,include具体体系结构下的Makefile,发生在400+行,此时这个SRCARCH变量已经被正确赋值了。



你可能感兴趣的:(Linux内核,Makefile)