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文件中有詳細的講解,上面我只是簡單實現了一下,但都是皮毛。