uboot编译分析
V= 1 –> Q = @ ,在一行命令前面加上@表示不会在终端输出命令
KCONFIG_CONFIG ?= .config
.config 默认是没有的,默认是需要使用命令“make xxx_defconofig”先对uboot进行配置,配置完成就会在uboot根目录下生成.config。如果后续自行调整了 uboot 的一些配置参数,那么这些新的配置参数就添加到了.config 中,而不是 xxx_defconfig。相当于 xxx_defconfig 只是一些初始配置,而.config 里面的才是实时有效的配置。
替换
$(var:”%“=%) –> 在var变量中进行替换,提取“ ”之间的内容
BOARD := $(CONFIG_SYS_BOARD:"%"=%)
强制执行
FORCE:
FORCE 是没有规则和依赖的,所以每次都会重新生成 FORCE。当 FORCE 作为其他目标的依赖时,由于 FORCE 总是被更新过的,因此依赖所在的规则总是会执行的。
- make xxx_defconfig执行
会匹配到
%config: scripts_basic outputmakefile FORCE
$(Q)$(MAKE) $(build)=scripts/kconfig $@
会执行
@make -f ./scripts/Makefile.build obj=scripts/basic
@make -f ./scripts/Makefile.build obj=scripts/kconfig xxx_defconfig
scripts_basic –> @make -f ./scripts/Makefile.build obj=scripts/basic
scripts/Makefile.build 分析
prefix := tpl
src := $(patsubst $(prefix)/%,%,$(obj)) #scripts/basic目录没有tpl,src=obj
ifeq ($(obj),$(src))
prefix := spl
src := $(patsubst $(prefix)/%,%,$(obj)) #scripts/basic目录没有spl,src=obj
ifeq ($(obj),$(src))
prefix := . #prefix=.
endif
endif
# The filename Kbuild has precedence over Makefile
kbuild-dir := $(if $(filter /%,$(src)),$(src),$(srctree)/$(src))
kbuild-file := $(if $(wildcard $(kbuild-dir)/Kbuild),$(kbuild-dir)/Kbuild,$(kbuild-dir)/Makefile) #kbuild-file= ./scripts/basic/Makefile
include $(kbuild-file)
# We keep a list of all modules in $(MODVERDIR)
__build: $(if $(KBUILD_BUILTIN),$(builtin-target) $(lib-target) $(extra-y)) \
$(if $(KBUILD_MODULES),$(obj-m) $(modorder-target)) \
$(subdir-ym) $(always)
@:
在顶层 Makefile 中,KBUILD_BUILTIN 为 1,KBUILD_MODULES 为 0,因此__build:$(builtin-target) $(lib-target) $(extra-y)) $(subdir-ym) $(always)
always=scripts/basic/fixdep
最终__build : scripts/basic/fixdep
-
%config目标
@make -f ./scripts/Makefile.build obj=scripts/kconfig xxx_defconfig | | src= scripts/kconfig kbuild-dir = ./scripts/kconfig kbuild-file = ./scripts/kconfig/Makefile include ./scripts/kconfig/Makefile | | %_defconfig: $(obj)/conf $(Q)$< $(silent) --defconfig=arch/$(SRCARCH)/configs/$@ $(Kconfig) | | silent=-s 或为空 SRCARCH=.. Kconfig=Kconfig | | @ scripts/kconfig/conf --defconfig=arch/../configs/xxx_defconfig Kconfig | | .config
-
make过程
PHONY := _all #命令行没有指定目标时,使用默认目标 | | ifeq ($(KBUILD_EXTMOD),) #不编译模块,所以 _all 依赖 all _all: all else _all: modules endif | | all: .binman_stamp inputs # all 依赖.binman_stamp inputs inputs: $(INPUTS-y) # Timestamp file to make sure that binman always runs .binman_stamp: FORCE @touch $@ | | INPUTS-y += u-boot.srec u-boot.bin u-boot.sym System.map binary_size_check | | # 根据.config里面的定义,有相关定义,INPUTS-$(var) = INPUTS-y,all相当于就多了依赖 INPUTS-$(CONFIG_ONENAND_U_BOOT) += u-boot-onenand.bin ifeq ($(CONFIG_SPL_FSL_PBL),y) INPUTS-$(CONFIG_RAMBOOT_PBL) += u-boot-with-spl-pbl.bin else ifneq ($(CONFIG_NXP_ESBC), y) # For Secure Boot The Image needs to be signed and Header must also # be included. So The image has to be built explicitly INPUTS-$(CONFIG_RAMBOOT_PBL) += u-boot.pbl endif
INPUTS-y 依赖的u-boot.bin就是我们需要的文件
# u-boot.bin --> u-boot-nodtb.bin
ifeq ($(CONFIG_MULTI_DTB_FIT),y)
u-boot.bin: u-boot-fit-dtb.bin FORCE
$(call if_changed,copy)
else ifeq ($(CONFIG_OF_SEPARATE).$(CONFIG_OF_OMIT_DTB),y.)
u-boot-dtb.bin: u-boot-nodtb.bin dts/dt.dtb FORCE
$(call if_changed,cat)
u-boot.bin: u-boot-dtb.bin FORCE
$(call if_changed,copy)
else
u-boot.bin: u-boot-nodtb.bin FORCE
$(call if_changed,copy) # if_change为一个函数,在scripts/Kbuild.include中定义-->在一些先决条件比目标新的时候,或者命令行有改变的时候,if_changed 就会执行一些命令
endif
|
|
u-boot-nodtb.bin: u-boot FORCE # u-boot-nodtb.bin --> u-boot
$(call if_changed,objcopy_uboot)
$(BOARD_SIZE_CHECK)
|
|
u-boot: $(u-boot-init) $(u-boot-main) $(u-boot-keep-syms-lto) u-boot.lds FORCE
$(call if_changed,u-boot__)
目标 u-boot
依赖于 u-boot_init、u-boot-main 和 u-boot.lds
u-boot-init := $(head-y)
|
|
head-y := arch/arm/cpu/$(CPU)/start.o # arch/arm/Makefile中定义
|
|
u-boot-init= arch/arm/cpu/armv7/start.o # 当 CPU=armv7时
目标u-boot-main
依赖 libs-y
libs-$(CONFIG_API) += api/
libs-$(HAVE_VENDOR_COMMON_LIB) += board/$(VENDOR)/common/
libs-y += boot/
libs-y += cmd/
libs-y += common/
libs-$(CONFIG_OF_EMBED) += dts/
libs-y += env/
libs-y += lib/
libs-y += fs/
libs-y += net/
libs-y += disk/
libs-y += drivers/
libs-$(CONFIG_SYS_FSL_DDR) += drivers/ddr/fsl/
libs-$(CONFIG_SYS_FSL_MMDC) += drivers/ddr/fsl/
libs-$(CONFIG_$(SPL_)ALTERA_SDRAM) += drivers/ddr/altera/
libs-y += drivers/usb/cdns3/
libs-y += drivers/usb/dwc3/
libs-y += drivers/usb/common/
libs-y += drivers/usb/emul/
libs-y += drivers/usb/eth/
libs-$(CONFIG_USB_DEVICE) += drivers/usb/gadget/
libs-$(CONFIG_USB_GADGET) += drivers/usb/gadget/
libs-$(CONFIG_USB_GADGET) += drivers/usb/gadget/udc/
libs-y += drivers/usb/host/
libs-y += drivers/usb/mtu3/
libs-y += drivers/usb/musb/
libs-y += drivers/usb/musb-new/
libs-y += drivers/usb/phy/
libs-y += drivers/usb/ulpi/
ifdef CONFIG_POST
libs-y += post/
endif
libs-$(CONFIG_UNIT_TEST) += test/
libs-$(CONFIG_UT_ENV) += test/env/
libs-$(CONFIG_UT_OPTEE) += test/optee/
libs-$(CONFIG_UT_OVERLAY) += test/overlay/
libs-y += $(if $(BOARDDIR),board/$(BOARDDIR)/)
libs-y := $(sort $(libs-y))
u-boot-dirs := $(patsubst %/,%,$(filter %/, $(libs-y))) tools examples
libs-y := $(patsubst %/, %/built-in.o, $(libs-y))
libs-y
就是 uboot 各个实际功能模块子目录的集合
libs-y := $(patsubst %/, %/built-in.o, $(libs-y))
上面语句会将 libs-y
目录下所有的 /
结尾的替换为/built-in.o
,比如drivers/dma/
就变为了drivers/dma/built-in.o
,相当于将 libs-y 改为所有子目录中built-in.o
文件的集合。
其他依赖和上面一样分析。
总结:
- 编译uboot需要先编译配置文件
.config
,实际上是使用scripts/kconfig/conf
工具根据 configs目录下指定的配置文件生成的; - make 的过程 生成二进制的
u-boot.bin
以及相关的u-boot
文件。