找入口
追蹤的第一件事情,還是找入口,就跟看C代碼我們需要先找到main函數一樣。
我在《u-boot.bin生成過程追蹤》一文中提到了"u-boot-dirs"變量,這個變量展開之後,是一系列的目錄。然後這些目錄作為目标,有如下的生成規則:
PHONY += $(u-boot-dirs)
$(u-boot-dirs): prepare scripts
$(Q)$(MAKE) $(build)[email protected]
u-boot-dirs展開是一系列目錄,如下:
arch/arm/cpu arch/arm/cpu/armv7 arch/arm/imx-common ......
我們以目錄"arch/arm/cpu"為例,将這個規則的指令行展開,得到:
$(Q)$(MAKE) -f $(srctree)/scripts/Makefile.build obj=arch/arm/cpu
這裡使用u-boot-dirs裡面的目錄作為obj的值,引入Makefile.build進行make建構。那麼建構built-in.o的規則應該就在這個Makefile裡面了。打開Makefile.build,第108行,有關于built-in.o的變量指派:
ifneq ($(strip $(obj-y) $(obj-m) $(obj-) $(subdir-m) $(lib-target)),)
builtin-target := $(obj)/built-in.o
endif
這裡,builtin-target指派為"arch/arm/cpu/built-in.o",這個builtin-target在第358行有一個對應規則:
#
# Rule to compile a set of .o files into one .o file
#
ifdef builtin-target
quiet_cmd_link_o_target = LD [email protected]
# If the list of objects to link is empty, just create an empty built-in.o
cmd_link_o_target = $(if $(strip $(obj-y)),\
$(LD) $(ld_flags) -r -o [email protected] $(filter $(obj-y), $^) \
$(cmd_secanalysis),\
rm -f [email protected]; $(AR) rcs$(KBUILD_ARFLAGS) [email protected])
$(builtin-target): $(obj-y) FORCE
$(call if_changed,link_o_target)
targets += $(builtin-target)
endif # builtin-target
這裡的builtin-target規則,應該就是built-in.o的入口了。
展開規則
上面我們找到了built-in.o的入口,就是builtin-target對應的規則。這個規則依賴$(obj-y),obj-y變量實際上是Makefile.build裡面根據obj參數包含另外的Makefile帶進來的。見Makefile.build第59行:
include $(kbuild-file)
我們以上面"obj=arch/arm/cpu"為例,這裡的include就變成:
include ./arch/arm/cpu/Makefile
在這個被引入的Makefile裡面,根據配置定義了obj-y變量的值。
builtin-target規則的指令調用了if_changed函數,這個函數展開之後是cmd_link_o_target的值,見規則以上該變量的定義。我們将該變量做适當展開,如下:
$(LD) $(ld_flags) -r -o [email protected] $(filter $(obj-y), $^) $(cmd_secanalysis),rm -f [email protected]; $(AR) rcs$(KBUILD_ARFLAGS) [email protected]
其中cmd_secanalysis變量定義在135行,這個變量根據配置來定義,如果相應配置沒有選擇,則該變量為空。這裡我們以實際的例子看下這個指令是怎樣的:
arm-poky-linux-gnueabi-ld.bfd -r -o arch/arm/cpu/armv7/mx6/built-in.o arch/arm/cpu/armv7/mx6/soc.o arch/arm/cpu/armv7/mx6/clock.o
如上,調用了連結器ld,使用了-r選項,該選項使ld輸出可重定位檔案。連結器輸入為各個源代碼檔案編譯的目标檔案。
以上就是built-in.o檔案的建構過程,是不是感覺特别簡單?