Linux内核Makefile

2019-07-13 05:02发布

注:以下文字大部分来自韦东山《嵌入式Linux应用开发完全手册》
Linux内核源码中含有很多个Makefile文件主要分为以下5类:                                         Linux内核Makefile文件分类 顶层Makefile 根据不同的平台,对各类target分类并调用相应的规则Makefile生成目标 .config 内核配置文件 arch/$(ARCH)/Makefile  具体平台相关的Makefile scripts/Makefile.* 通用规则文件,面向所有的Kbuild Makefiles,所起的作用可以从后缀名中得知。 各子目录下的Makefile 文件 由其上层目录的Makefile调用,执行其上层传递下来的命令
Linux的Makefile有三个作用: 1.决定编译那些文件; 2.怎样编译这些文件; 3.怎样连接这些文件,最重要的是它们的顺序如何;
1.决定编译那些文件: Linux内核的编译过程从顶层Makefile开始,然后递归地进入各级子目录调用它们的Makefile,分为3个步骤: 1)顶层Makefile决定内核目录下哪些子目录将被编进内核。 2)arch/$(ARCH)/Makefile决定arch/$(ARCH)目录下哪些文件、哪些目录将被编进内核。 3)各级子目录下的Makefile决定所在目录下哪些文件将被编进内核,哪些文件将被编进模块(说的是驱动程序),进入哪些子目录继续调用它们的Makefile。
先看步骤1),在顶层Makefile中可以看到如下内容: 433 init-y := init/
434 drivers-y := drivers/ sound/
435 net-y := net/
436 libs-y := lib/
437 core-y := usr/
556 core-y += kernel/ mm/ fs/ ipc/ security/ crypto/ block/
可见,顶层Makefile将内核源码目录下的13个子目录分为5类:init-y、drivers-y、net-y、libs-y、core-y。(core-y包含了kernel、mm、fs、ipc、security、crypto、block,共7个文件夹)。内核源码目录下有17个子目录,除去include目录和后面两个不包含内核代码的目录外,还有一个arch目录没有出现在内核中。它在arch/$(ARCH)/Makefile中被包含进内核,在顶层Makefile中直接包含了这个Makefile,如下所示: 491 include $(srctree)/arch/$(ARCH)/Makefile 对于上面出现的ARCH变量,可以在执行make命令传入,比如“make ARCH=arm...”。另外,对于非x86平台,还需要指定交叉编译工具,这也可以在执行make命令时传入,比如“make CROSS_COMPILE=arm-linux-...”。为了方便,常在Makefile中进行如下修改: 修改前: 185 ARCH?= $(SUBARCH)
186 CROSS_COMPILE ?=
修改后: 185 ARCH?= arm
186 CROSS_COMPILE ?=arm-linux-

再来看步骤2),在arch/arm/Makefile中可以看到如下内容: 94 head-y:= arch/arm/kernel/head$(MMUEXT).o arch/arm/kernel/init_task.o 171 core-y+= arch/arm/kernel/ arch/arm/mm/ arch/arm/common/
172 core-y += $(MACHINE)
173 core-$(CONFIG_ARCH_S3C2410) += arch/arm/mach-s3c2400/
174 core-$(CONFIG_ARCH_S3C2410) += arch/arm/mach-s3c2412/
175 core-$(CONFIG_ARCH_S3C2410) += arch/arm/mach-s3c2440/
191 libs-y:= arch/arm/lib/ $(libs-y)     从第94行可知,除前面的5类子目录外,又出现了另一类:head-y,不过它直接以文件名出现。其中的MMUEXT在arch/arm/Makefile前面定义,对于没有MMU的处理器,MMUEXT的值为-nommu,使用文件head-nommu.s;对于有MMU的处理器,MMUEXT的值为空,使用文件head.s。     arch/arm/Makefile中的171、172、173等行代码进一步扩展了core-y的内容,第191行扩展了lib-y的内容,这些都是体系结构相关的目录。第173~175行中的CONFIG_ARCH_S3C2410在配置内核时定义,它的值有三种:y、m和空。y表示编进内核,m表示编为模块,空表示不使用。     编译内核时,将依次进入inti-y、core-y、lib-y、drivers-y和net-y所列出的目录中执行它们的Makefile,每个子目录都会生成一个built-in.o(在lib-y所列的目录下,有可能生成lib.a文件)。最后head-y所表示的文件将和这些built-in.o、lib.a一起被连接成内核映像文件vmlinux。     最后,看一下步骤3),各子目录的Makefile怎么进行的。     在配置内核后,将会生成配置文件.config。内核使用语句 441 #Read in config 442 -include include/config/auto.conf 间接包含了.config文件,然后就根据.config中定义的各个变量决定编译哪些文件。 之所以说是间接,是因为包含的是auto.conf,而auto.conf是将.config中的注释去掉,再根据顶层Makefile中定义的变量增加了一些变量的文件。 auto.conf的格式与.config相同,下面是一个片段: CONFIG_ARCH_SMDK2410=y CONFIG_ARCH_S3C2440=y #.config中没有下面这行,它是根据顶层Makefile中定义的内核版本号增加的 CONFIG_KERNELVERSION="2.6.22.6" #.config中没有下面这行,它是根据Makefile中定义的ARCH变量增加的 CONFIG_ARCH="arm" CONFIG_JFFS2_FS=y CONFIG_LEDS_S3C24XX=m
在include/configauto.conf文件中,变量的值主要有两类:“y”和“m”。各级子目录的Makefile使用这些变量来决定哪些文件被编进内核,哪些被编为模块。 要进入哪些下一级子目录继续编译,通过下面4中方法来确定(obj-y、obj-m、lib-y都是Makefile中的变量) 1))obj-y决定哪些文件被编进(built-in)内核     obj-y中定义的.o文件由当前目录下的.c或.s文件编译生成,它们连同下级子目录的built-in.o文件一起被组合成(使用“$(LD) -r”命令)当前目录下的built-in.o文件。这个built-in.o将被它上一层的Makefile使用。     obj-y中各个.o文件是有顺序的,因为内核中用module_init()或_initcall定义的函数将按照它们的连接顺序被调用。 2))obj-m用来定义哪些文件将被编译成可加载模块     obj-m中定义的.o文件由当前目录下的.c或.s文件编译生成,它们不会被编进built-in.o中,而是被编程可加载模块。 3))lib-y用来定义哪些文件被编成库文件     lib-y中定义.o文件由当前目录下的.c或.s文件编译生成,它们被打包成当前目录下的一个库文件:lib.a     要把这个lib.a编进内核,需要在顶层Makefile中lib-y变量中列出当前目录。要编成库文件的内核代码一般都在这两个目录下:lib/、arch/$(ARCH)/lib/ 4))obj-y、obj-m还可以用来指定要进入的下一层目录。
2.怎样编译这些文件

3.怎样连接这些文件,它们的顺序如何 顶层Makefile和arch/$(ARCH)/Makefile中定义了6类目录:head-y、init-y、drivers-y、net-y、libs-y和core-y。
可见,出head-y外,其余都是目录名。在顶层Makefile中,这些目录名的后面直接加上built-in.o或lib.a,表示要连接进内核的文件,如下:


第604行中,vmlinux-all表示所有构成内核映像文件vmlinux的目标文件。把602和603代入604,可知目标文件顺序为:head-y、init-y、core-y、libs-y、drivers-y、net-y,即:
因此编译器就根据这个内容把内核映像文件vmlinux编译出来了。
。。。 顶层Makefile按照一定的顺序组织文件,根据连接脚本arch/$(ARCH)/kernel/vmlinux.lds生成内核映像文件vmlinux。