在Linux移植之make uImage編譯過程分析中羅列出了最後連接生成vmlinux的過程。能夠看到在每一個子目錄下都有一個built-in.o文件。對於此產生了疑問built-in.o文件是根據什麼產生的。html
arm-linux-ld -EL -p --no-undefined -X -o vmlinux -T arch/arm/kernel/vmlinux.lds arch/arm/kernel/head.o arch/arm/kernel/init_task.o init/built-in.o --start-group usr/built-in.o arch/arm/kernel/built-in.o arch/arm/mm/built-in.o arch/arm/common/built-in.o arch/arm/mach-s3c2410/built-in.o arch/arm/mach-s3c2400/built-in.o arch/arm/mach-s3c2412/built-in.o arch/arm/mach-s3c2440/built-in.o arch/arm/mach-s3c2442/built-in.o arch/arm/mach-s3c2443/built-in.o arch/arm/nwfpe/built-in.o arch/arm/plat-s3c24xx/built-in.o kernel/built-in.o mm/built-in.o fs/built-in.o ipc/built-in.o security/built-in.o crypto/built-in.o block/built-in.o arch/arm/lib/lib.a lib/lib.a arch/arm/lib/built-in.o lib/built-in.o drivers/built-in.o sound/built-in.o net/built-in.o --end-group .tmp_kallsyms2.o
一、測試,在linux目錄下添加一個test文件夾,在文件夾裏面添加了test.c 和 Makefile。測試是否也會生成built-in.o文件linux
二、從頂層Makefile文件開始分析built-in.o原理vim
三、遞歸規則函數
一、測試,在linux目錄下添加一個test文件夾,在文件夾裏面添加了test.c 和 Makefile。測試是否也會生成built-in.o文件post
a、mkdir test,建立test文件夾測試
b、cd test,進入test文件夾ui
d、vim Makefile,在裏面建立Makefileurl
# #Makefile for the linux kernel makefile experiment. # obj-y := test.o
e、vim test.c,在裏面建立C文件spa
#include <linux/export.h> int test_global = 0;
f、修改頂層Makefile,在core-y後面增長test/目錄code
-core-y += kernel/ mm/ fs/ ipc/ security/ crypto/ block/ +core-y += kernel/ mm/ fs/ ipc/ security/ crypto/ block/ test/
g、make uImage後觀察到在連接的過程當中多出了test/built-in.o 文件。測試成功
arm-linux-ld -EL -p --no-undefined -X -o .tmp_vmlinux1 -T arch/arm/kernel/vmlinux.lds arch/arm/kernel/head.o arch/arm/kernel/init_task.o
init/built-in.o --start-group usr/built-in.o arch/arm/kernel/built-in.o arch/arm/mm/built-in.o arch/arm/common/built-in.o
arch/arm/mach-s3c2410/built-in.o arch/arm/mach-s3c2400/built-in.o arch/arm/mach-s3c2412/built-in.o arch/arm/mach-s3c2440/built-in.o
arch/arm/mach-s3c2442/built-in.o arch/arm/mach-s3c2443/built-in.o arch/arm/nwfpe/built-in.o arch/arm/plat-s3c24xx/built-in.o
kernel/built-in.o mm/built-in.o fs/built-in.o ipc/built-in.o security/built-in.o crypto/built-in.o block/built-in.o test/built-in.o
arch/arm/lib/lib.a lib/lib.a arch/arm/lib/built-in.o lib/built-in.o drivers/built-in.o sound/built-in.o net/built-in.o --end-group
二、從頂層Makefile文件開始分析built-in.o原理,在測試成功後,要分析是怎麼作到更改了幾個文件就能產生test/built-in.o而且編譯進內核的。
從頂層Makefile開始分析,vmlinux-dirs包含了全部的linux子目錄
vmlinux-dirs := $(patsubst %/,%,$(filter %/, $(init-y) $(init-m) \ $(core-y) $(core-m) $(drivers-y) $(drivers-m) \ $(net-y) $(net-m) $(libs-y) $(libs-m)))
$(patsubst <pattern>,<replacement>,<text> ) 名稱:模式字符串替換函數——patsubst。 功能:查找<text>中的單詞(單詞以「空格」、「Tab」或「回車」「 換行」分隔)是否符合模 式<pattern>,若是匹配的話,則以<replacement>替換。這裏,<pattern>能夠包括通配符「%」, 表示任意長度的字串。若是<replacement>中也包含「%」,那麼,<replacement>中的這個「%」 將是<pattern>中的那個「%」所表明的字串。(能夠用「\」來轉義,以「\%」來表示真實含 義的「%」字符) 返回:函數返回被替換事後的字符串。
$(filter <pattern...>,<text> ) 名稱:過濾函數——filter。 功能:以<pattern>模式過濾<text>字符串中的單詞,保留符合模式<pattern>的單詞。能夠有 多個模式。 返回:返回符合模式<pattern>的字串。
另外在arch/arm/Makefile下也定義了一些文件夾:
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/ 176 core-$(CONFIG_ARCH_S3C2410) += arch/arm/mach-s3c2442/ 177 core-$(CONFIG_ARCH_S3C2410) += arch/arm/mach-s3c2443/ 178 core-$(CONFIG_FPE_NWFPE) += arch/arm/nwfpe/ 179 core-$(CONFIG_FPE_FASTFPE) += $(FASTFPE_OBJ) 180 core-$(CONFIG_VFP) += arch/arm/vfp/ 181 182 # If we have a common platform directory, then include it in the build. 183 core-$(CONFIG_PLAT_IOP) += arch/arm/plat-iop/ 184 core-$(CONFIG_ARCH_OMAP) += arch/arm/plat-omap/ 185 core-$(CONFIG_PLAT_S3C24XX) += arch/arm/plat-s3c24xx/ 186 187 drivers-$(CONFIG_OPROFILE) += arch/arm/oprofile/ 188 drivers-$(CONFIG_ARCH_CLPS7500) += drivers/acorn/char/ 189 drivers-$(CONFIG_ARCH_L7200) += drivers/acorn/char/ 190 191 libs-y := arch/arm/lib/ $(libs-y)
展開獲得
vmlinux-dir = init usr \ arch/arm/kernel arch/arm/mm arch/arm/common arch/arm/mach-s3c2410 arch/arm/mach-s3c2400 arch/arm/mach-s3c2412 arch/arm/mach-s3c2440 \ arch/arm/mach-s3c2442 arch/arm/mach-s3c2443 arch/arm/nwfpe arch/arm/plat-s3c24xx \ kernel mm fs ipc security crypto block test \ arch/arm/lib lib arch/arm/lib \ drivers sound net \
繼續看頂層Makefile生成vmlinux-dirs的規則以下:
764 $(vmlinux-dirs): prepare scripts 765 $(Q)$(MAKE) $(build)=$@
以建立的test目錄爲例:展開獲得。它的意思是調用scripts/Makefile.build。令參數obj=test,而後make。
make -f scripts/Makefile.build obj=test
接着進入scripts/Makefile.build繼續分析,它的默認目標是__build:
07 PHONY := __build 08 __build: 83 __build: $(if $(KBUILD_BUILTIN),$(builtin-target) $(lib-target) $(extra-y)) \ 84 $(if $(KBUILD_MODULES),$(obj-m)) \ 85 $(subdir-ym) $(always) 86 @:
接着看builtin-target、lib-target,它們被定義的條件是obj-%、lib-%不能爲空
73 ifneq ($(strip $(lib-y) $(lib-m) $(lib-n) $(lib-)),) 74 lib-target := $(obj)/lib.a 75 endif 76 77 ifneq ($(strip $(obj-y) $(obj-m) $(obj-n) $(obj-) $(lib-target)),) 78 builtin-target := $(obj)/built-in.o 79 endif
名稱:去空格函數——strip。 功能:去掉<string>字串中開頭和結尾的空字符。 返回:返回被去掉空格的字符串值。
接着看生成builtin-target的規則,lib-target的規則相似,仍是在scripts/Makefile.build裏找到以下規則
254 # To build objects in subdirs, we need to descend into the directories 255 $(sort $(subdir-obj-y)): $(subdir-ym) ; 256 257 # 258 # Rule to compile a set of .o files into one .o file 259 # 260 ifdef builtin-target 261 quiet_cmd_link_o_target = LD $@ 262 # If the list of objects to link is empty, just create an empty built-in.o 263 cmd_link_o_target = $(if $(strip $(obj-y)),\ 264 $(LD) $(ld_flags) -r -o $@ $(filter $(obj-y), $^),\ 265 rm -f $@; $(AR) rcs $@) 266 267 $(builtin-target): $(obj-y) FORCE 268 $(call if_changed,link_o_target) 269 270 targets += $(builtin-target) 271 endif # builtin-target
調用if_changed函數,進入scripts/Kbuild.include中
167 if_changed = $(if $(strip $(any-prereq) $(arg-check)), \ 168 @set -e; \ 169 $(echo-cmd) $(cmd_$(1)); \ 170 echo 'cmd_$@ := $(make-cmd)' > $(dot-target).cmd)
能夠看到最後調用的是cmd_link_o_target 腳本,回到scripts/Makefile.build中:
257 # 258 # Rule to compile a set of .o files into one .o file 259 # 260 ifdef builtin-target 261 quiet_cmd_link_o_target = LD $@ 262 # If the list of objects to link is empty, just create an empty built-in.o 263 cmd_link_o_target = $(if $(strip $(obj-y)),\ 264 $(LD) $(ld_flags) -r -o $@ $(filter $(obj-y), $^),\ 265 rm -f $@; $(AR) rcs $@)
其中obj-y=test.o定義在test目錄下的Makefile中,以下在scripts/Makefile.build中include了$(kbuild-dir)/Makefile,即test/Makefile
16 kbuild-dir := $(if $(filter /%,$(src)),$(src),$(srctree)/$(src)) 17 include $(if $(wildcard $(kbuild-dir)/Kbuild), $(kbuild-dir)/Kbuild, $(kbuild-dir)/Makefile)
將規則展開獲得:最終獲得了test/built-in.o
cmd_link_o_target = arm-linux-ld -EL -r -o test/built-in.o test.o arm-linux-ar rcs test/built-in.o
三、遞歸規則。若是在子目錄下還有子目錄編譯系統會怎麼操做呢,下面就講述遞歸的規則:
繼續看scripts/Makefile.build,它包含了scripts/Makefile.lib
19 include scripts/Makefile.lib
接着看到scripts/Makefile.lib,裏面定義了subdir-ym 這個變量表示的是若是obj-y含有文件夾則將文件夾放到subdir-ym中
24 __subdir-y := $(patsubst %/,%,$(filter %/, $(obj-y))) 25 subdir-y += $(__subdir-y) 26 __subdir-m := $(patsubst %/,%,$(filter %/, $(obj-m))) 27 subdir-m += $(__subdir-m) 28 obj-y := $(patsubst %/, %/built-in.o, $(obj-y)) 29 obj-m := $(filter-out %/, $(obj-m)) 30 31 # Subdirectories we need to descend into 32 33 subdir-ym := $(sort $(subdir-y) $(subdir-m))
繼續回到scripts/Makefile.build,看到有關subdir-y的規則
322 $(subdir-ym): 333 $(Q)$(MAKE) $(build)=$@
能夠看到這個規則與第二部分的規則很相似,這是一個遞歸調用,scripts/Makefile.build調用本身生成subdir-ym/built-in.o。具體分析與第二部分同樣。下面截圖自第二部分分析
子目錄下的built-in.o 就是這麼生成的。參考自https://www.ibm.com/developerworks/community/blogs/5144904d-5d75-45ed-9d2b-cf1754ee936a/entry/kernel-build-system?lang=en