Documentation/kbuild/makefiles.txt描述如下:
50 The Makefiles have five parts: 51 52 Makefile 总Makefile,控制内核的编译 53 .config 内核配置文件,配置内核时生成,如make menuconfig后 54 arch/$(ARCH)/Makefile 对应体系结构的Makefile 55 scripts/Makefile.* Makefile共用的规则,如图形配置界面。 56 kbuild Makefiles 各子目录下的Makefile,被上层的Makefile调用 |
简单来说,编译内核会执行以下事情。
1.make menuconfig
1.1拷贝一个对应体系结构的配置文件到主目录下并改名为.config,这样就在make menuconfig生成的图形配置中已经有了一些默认的配置,减少用户的劳动量。
1.2从内核顶层目录的Makefile决定编译的体系结构(ARCH).编译工具 (CROSS_COMPILE)和需要进去编译的目录。
1.3根据总Makefile的ARCH变量,进入相应体系结构的目录,读取arch/$ (ARCH)/Makefile,决定对应的体系结构下还有哪些目录需要编译。
1.4根据arch/$(ARCH)/Makefile,一个一个地递归进入指定的目录下调用该目录下的makefile,并根据目录下的Kconfig生成配置界面并由用户决定将该文件编译成模块还是编译进内核。
1.5配置完毕后保存退出,会更改原来的.config的内容。
2.make
1.1将生成的.config去掉注释,新建一份配置文件,文件名为include/config/auto.conf。
1.2根据配置文件的要求,将需要编译的文件的各个子目录下生成一个.o或者.a文件,然后由总Makefile指定的连接脚本arch/$(ARCH)/kernel/vmlinux.lds生成vmlinux,并通过压缩变成bzImage,或者按要求在对应的子目录下编译成模块。
但是,具体是怎么生成配置文件的呢?
注:我使用的内核是被修改过的,可能有些地方和原内核不一样,如我内核里面$(ARCH)写成$(SRCARCH)。还有在文件中的行数和原内核不一致,但这些不影响分析,搜索一下就出来了。
1.在总Makefile中,根据以下语句进入需要编译的目录
470 # Objects we will link into vmlinux / subdirs we need to visit 471 init-y := init/ 472 drivers-y := drivers/ sound/ firmware/ 473 net-y := net/ 474 libs-y := lib/ 475 core-y := usr/ 476 endif # KBUILD_EXTMOD 639 core-y += kernel/ mm/ fs/ ipc/ security/ crypto/ block/ #另外还有一个体系相关的arch目录 529 include $(srctree)/arch/$(SRCARCH)/Makefile
|
这样,就根据了体系结构决定了需要进去编译的目录了。
2.在总Makefile中包含的目录还是不够的,内核还需要根据对应的CPU体系架构,决定还需要将哪些子目录将要编译进内核,在总Makefile中进去读取相应体系结构的Makefile:arch/$(SRCARCH)/Makefile。
在总Makefile和体系架构下的arch/(SRCARCH)/Makefile中包含的子目录会根据该目录下的Makefile的要求编译成模块还是编译进内核,当然也可以不编译。
如在 arch/arm/Makefile 下:
187 # If we have a machine-specific directory, then include it in the build. 188 core-y += arch/arm/kernel/ arch/arm/mm/ arch/arm/common/ 189 core-y += $(machdirs) $(platdirs) 190 core-$(CONFIG_FPE_NWFPE) += arch/arm/nwfpe/ 191 core-$(CONFIG_FPE_FASTFPE) += $(FASTFPE_OBJ) 192 core-$(CONFIG_VFP) += arch/arm/vfp/ 193 194 drivers-$(CONFIG_OPROFILE) += arch/arm/oprofile/ 195 196 libs-y := arch/arm/lib/ $(libs-y)
|
其中,y表示编译成模块,m表示编译进内核(上面没有,因为默认情况下ARM全部编译进内核),但$(CONFIG_OPROFILE)又是什么呢?
这些是根据用户在make menuconfig中设置后,生成的值赋给了CONFIG_OPROFILE。这是由各子目录下的Kconfig提供选项功用户选择并配置。如arch/arm/Kconfig。
另外有些配置会根据arch/$(ARCH)/Kconfig文件通过Kconfig的语法source读取各个包含的子目录Kconfig来生成一个配置界面。每个Makefile目录下都有一个对应Kconfig文件,用于生成配置界面来给用户决定内核如何配置。
总结Kconfig的作用:
2.1.在make menuconfig下可以配置选项;
2.2.在.config中确定CONFIG_XXX的的值。
3.只是读取以上的两个Makefile还是不够了,内核还会把包含的子目录一层一层的读取它里面的Makefile和Kconfig。
假设我现在配置内核
1.最简单的方法,直接修改子目录的Makefile
如在我要取消s3c2440的时钟(当然这是必须要开的,只是举例)。
可以直接修改arch/arm/mach-s3c2440/Makefile
12 obj-$(CONFIG_CPU_S3C2440) += s3c2440.o dsc.o 13 obj-$(CONFIG_CPU_S3C2440) += irq.o 14 obj-$(CONFIG_CPU_S3C2440) += clock.o 15 obj-$(CONFIG_S3C2440_DMA) += dma.o
|
将obj-$(CONFIG_CPU_S3C2440) += clock.o改为
obj- += clock.o
也可以编译成模块:
obj-m += clock.o
2.当然有更方便的通过图形界面,make menuconfig,接下来我实现一下如何将一个选项加入到图形配置界面中。
2.1.进入内核目录
cd linux-2.6.29
2.2.在driver目录下模拟一个名为test1驱动的文件夹
mkdir driver/test1
2.3.在test1目录下随便写个C文件
cd driver/test1
vim test1.c
1 void foo() 2 { 3 ; 4 }
|
2.4.在目录下编写一个简单的Makefile
vim Makefile
obj-$(CONFIG_TEST1) += test1.o |
CONFIG_TEST1是决定test1是否编译进内核或者编译成模块的。这就通过Kconfig由用户在make menuconfig中选择。
2.5.所以还要在目录下写一个Kconfig
vim Kconfig
1 menu "test1 driver here" 2 config TEST1 3 bool "xiaobai test1 driver" 4 help 5 This is test1 6 endmenu
|
说白了,就是在图形配置的driver下多了一个配置选项,用户配置后将CONFIG_TEST1的值存放在.config中,Makefile通过读取.config的去注释版autoconf读取到CONFIG_TEST的值,再进行编译。但是,以上几步还不能达到目的,因为虽然在总Makefile中已经包含了目录driver,但是driver目录的Makefile中并没有包含test目录。因此需要在driver/Makefile中添加:
2.6.vim driver/Makefile
再最后加上一句:
104 obj-$(CONFIG_OF) += of/ 105 obj-$(CONFIG_SSB) += ssb/ 106 obj-$(CONFIG_VIRTIO) += virtio/ 107 obj-$(CONFIG_STAGING) += staging/ 108 obj-y += platform/ 109 obj-$(CONFIG_TEST1) += test1/ //添加这句
|
虽然Makefile中已经包含了,但这样还是不行。因为当需要配置ARM时,ARM结构下的Kconfig并没有包含test的Kconfig。这样的话就不会出现在图形配置界面中,因此在arch/arm/Kconfig中添加语句。
2.7.vim arch/arm/Kconfig
1230 menu "Device Drivers" 1231 1232 source "drivers/base/Kconfig" ….............................................. 1328 source "drivers/staging/Kconfig" 1329 1330 source "drivers/test1/Kconfig" 1331 1332 endmenu
|
大功告成!
这样,make menuconfig界面写的Driver Devices下就多了一个"test1 driver here"的目录,里面有一个配置选项"xiaobai test1 driver"。
Kconfig文件的语法在documentation/kbuild/kconfig-language.txt文件中有详细的讲解,上面我只是简单实现了一下,但都是皮毛。