正点原子imx6ullUBOOT顶层Makefile学习笔记

Posted 西邮菜

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了正点原子imx6ullUBOOT顶层Makefile学习笔记相关的知识,希望对你有一定的参考价值。

跟据正点原子的linux开发板手册与视频学习了uboot的顶层makefile工作流程。

一、准备阶段

$(MAKE) -C subdir:调用subdir目录下的makefile文件,make支持递归调用。

ifeq ("$(origin V)", "command line")
  KBUILD_VERBOSE = $(V)
endif
ifndef KBUILD_VERBOSE
  KBUILD_VERBOSE = 0
endif

ifeq ($(KBUILD_VERBOSE),1)
  quiet =
  Q =
else
  quiet=quiet_
  Q = @
endif

有两个变量是默认传给子make的:SHELL和MAKEFLAGS。可以使用unexport声明不导出。

uboot默认输出短命令,需要设置V=1来实现完整命令的输出。

origin 用于告诉你变量是哪来的,origin 函数的返回值就是变量来源。

make 在执行的时候默认会在终 端输出命令,但是在命令前面加上“@”就不会在终端输出命令了。

make 在执行的时候默认会在终 端输出命令,但是在命令前面加上“@”就不会在终端输出命令了。

uboot 支持代码检查,使用命令“make C=1”使能代码检查,检查那些需要重新编译的文 件。“make C=2”用于检查所有的源码文件。

在 uboot 中允许单独编译某个模块,使用命令“make M=dir”即可。

二、配置UBOOT——make xxx_defconfig 过程

在编译uboot前需要配置UBOOT,通过使用make ×××_defonfig命令来配置uboot,配置后会在uboot根目录下生成.config,实际.config的内容和前面***_deconfig内容一致,但是后续调整uboot的设置时需要通过.config修改,.config 里面的才是实时有效的配置。

在makefile中找到了%config的依赖关系。

%config: scripts_basic outputmakefile FORCE
$(Q)$(MAKE) $(build)=scripts/kconfig $@

FORCE没有依赖,他总会被执行。目标文件是%config,依赖文件是scripts_basic、outputmakefile。

PHONY += scripts_basic
scripts_basic:
	$(Q)$(MAKE) $(build)=scripts/basic
	$(Q)rm -f .tmp_quiet_recordmcount

scripts/basic/%: scripts_basic ;

PHONY += outputmakefile
outputmakefile:
ifneq ($(KBUILD_SRC),)
	$(Q)ln -fsn $(srctree) source
	$(Q)$(CONFIG_SHELL) $(srctree)/scripts/mkmakefile \\
	    $(srctree) $(objtree) $(VERSION) $(PATCHLEVEL)
endif

先看outputmakefile,他首先判断$(KBUILD_SRC)是否不为空,但是析KBUILD_SRC 为空,所以 outputmakefile 无效。后面大头主要就是scripts_basic。

PHONY += scripts_basic
scripts_basic:
	$(Q)$(MAKE) $(build)=scripts/basic
	$(Q)rm -f .tmp_quiet_recordmcount

# To avoid any implicit rule to kick in, define an empty command.
scripts/basic/%: scripts_basic ;

build 是在 scripts/Kbuild.include 文件中有定义build := -f $(srctree)/scripts/Makefile.build obj,srctree 为”.”。

所以scripts_basic与%config展开为

scripts_basic:
make -f ./scripts/Makefile.build obj=scripts/basic 
rm -f . tmp_quiet_recordmcount 

%config: scripts_basic outputmakefile FORCE
#######$(Q)$(MAKE) $(build)=scripts/kconfig $@######
make -f ./scripts/Makefile.build obj=scripts/kconfig xxx_defconfig
###$@是目标文件执行make xxx_defconfig时,目标文件就是xxx_defconfig。

执行命令配置uboot时make mx6ull_14x14_ddr512_emmc_defconfig V=1可以看到结果就是上面解析出来的两个命令:

 一、首先看看%config的依赖文件scripts_basic对应的命令:make -f ./scripts/Makefile.build obj=scripts/basic ,可以看到调用了Makefile.build 文件,下面看这个文件。

8 # Modified for U-Boot
9 prefix := tpl
10 src := $(patsubst $(prefix)/%,%,$(obj))
11 ifeq ($(obj),$(src))
12 prefix := spl
13 src := $(patsubst $(prefix)/%,%,$(obj))
14 ifeq ($(obj),$(src))
15 prefix := .
16 endif
17 endif

得出src=scripts/basic,prefix=.。

56 # The filename Kbuild has precedence over Makefile
57 kbuild-dir := $(if $(filter /%,$(src)),$(src),$(srctree)/$(src))
58 kbuild-file := $(if $(wildcard $(kbuild-dir)/Kbuild),$(kbuilddir)/Kbuild,$(kbuild-dir)/Makefile)
59 include $(kbuild-file)

得出kbuild_dir=./scripts/basic,kbuild-file= ./scripts/basic/Makefile。

116 __build: $(if $(KBUILD_BUILTIN),$(builtin-target) $(lib-target)
$(extra-y)) \\
117 $(if $(KBUILD_MODULES),$(obj-m) $(modorder-target)) \\
118 $(subdir-ym) $(always)
119 @:

__build 是默认目标因为命令“@make -f ./scripts/Makefile.build obj=scripts/basic”没有指 定目标,所以会使用到默认目标:__build。在顶层 Makefile 中,KBUILD_BUILTIN 为 1, KBUILD_MODULES 为 0,因此展开后目标__build 为: __build:$(builtin-target) $(lib-target) $(extra-y)) $(subdir-ym) $(always) @:后面五个是他的依赖。输出后发现只有always有效,所以最终_build是:

__build: scripts/basic/fixdep
@:

综上所述:scripts_basic 目标的作用就是编译出 scripts/basic/fixdep 这个软件。

 

二、然后看看%config对应的命令:make -f ./scripts/Makefile.build obj=scripts/kconfig xxx_defconfig。

Makefilke.build 会读取 scripts/kconfig/Makefile 中的内容。内容如下:

113 %_defconfig: $(obj)/conf
114 $(Q)$< $(silent) --defconfig=arch/$(SRCARCH)/configs/$@ 
$(Kconfig)
115
116 # Added for U-Boot (backward compatibility)
117 %_config: %_defconfig
118 @:

目标%_defconfig 刚好和我们输入的 xxx_defconfig 匹配,所以会执行这条规则。依赖为 $(obj)/conf,展开后就是 scripts/kconfig/conf。接下来就是检查并生成依赖 scripts/kconfig/conf。再执行目标%_defconfig 的命令:

@(Q)$< $(silent) --defconfig=arch/$(SRCARCH)/configs/$@ $(Kconfig)

解析后:@ scripts/kconfig/conf --defconfig=arch/../configs/xxx_defconfig Kconfig

上述命令用到了 xxx_defconfig 文件,比如 mx6ull_alientek_emmc_defconfig。这里会将 mx6ull_alientek_emmc_defconfig 中的配置输出到.config 文件中,最终生成 uboot 根目录下 的.config 文件。make xxx_defconfig 执行流程:

 

三、编译UBOOT

配置好 uboot 以后就可以直接 make 编译了,因为没有指明目标,所以会使用默认目标,主 Makefile 中的默认目标如下:

PHONY := _all  

_all:

_all 的依赖就是 all。

802 all: $(ALL-y)
803 ifneq ($(CONFIG_SYS_GENERIC_BOARD),y)
804 @echo "===================== WARNING ======================"
805 @echo "Please convert this board to generic board."
806 @echo "Otherwise it will be removed by the end of 2014."
807 @echo "See doc/README.generic-board for further information"
808 @echo "===================================================="
809 endif
810 ifeq ($(CONFIG_DM_I2C_COMPAT),y)
811 @echo "===================== WARNING ======================"
812 @echo "This board uses CONFIG_DM_I2C_COMPAT. Please remove"
813 @echo "(possibly in a subsequent patch in your series)"
814 @echo "before sending patches to the mailing list."
815 @echo "===================================================="
816 endif

all又依赖变量ALL-y。

730 # Always append ALL so that arch config.mk's can add custom ones
731 ALL-y += u-boot.srec u-boot.bin u-boot.sym System.map u-boot.cfg 
binary_size_check
732
733 ALL-$(CONFIG_ONENAND_U_BOOT) += u-boot-onenand.bin
734 ifeq ($(CONFIG_SPL_FSL_PBL),y)
735 ALL-$(CONFIG_RAMBOOT_PBL) += u-boot-with-spl-pbl.bin
736 else
737 ifneq ($(CONFIG_SECURE_BOOT), y)
738 # For Secure Boot The Image needs to be signed and Header must also
739 # be included. So The image has to be built explicitly
740 ALL-$(CONFIG_RAMBOOT_PBL) += u-boot.pbl
741 endif
742 endif
743 ALL-$(CONFIG_SPL) += spl/u-boot-spl.bin
744 ALL-$(CONFIG_SPL_FRAMEWORK) += u-boot.img
745 ALL-$(CONFIG_TPL) += tpl/u-boot-tpl.bin
。。。。。。。
。。。。。。。
。。。。。。。

ALL-y 包含 u-boot.srec、u-boot.bin、u-boot.sym、 System.map、u-boot.cfg 和 binary_size_check 这几个文件。根据 uboot 的配置情况也可能包含其他的文件,就是后面那些。

ALL-y 里面有个 u-boot.bin,这个就是我们最终需要的 uboot 二进制可执行文件。

832 u-boot.bin: u-boot-nodtb.bin FORCE
833 $(call if_changed,copy)

目标 u-boot.bin 依赖于 u-boot-nodtb.bin,命令为$(call if_changed,copy) 。

866 u-boot-nodtb.bin: u-boot FORCE
867 $(call if_changed,objcopy)
868 $(call DO_STATIC_RELA,$<,$@,$(CONFIG_SYS_TEXT_BASE))
869 $(BOARD_SIZE_CHECK)

目标 u-boot-nodtb.bin 又依赖于 u-boot。

1170 u-boot: $(u-boot-init) $(u-boot-main) u-boot.lds FORCE
1171 $(call if_changed,u-boot__)
1172 ifeq ($(CONFIG_KALLSYMS),y)
1173 $(call cmd,smap)
1174 $(call cmd,u-boot__) common/system_map.o
1175 endif

目标 u-boot 依赖于 u-boot_init、u-boot-main 和 u-boot.lds,u-boot_init 和 u-boot-main 是两个 变量, u-boot.lds是链接脚本。

u-boot-init := $(head-y)
u-boot-main := $(libs-y)
head-y 在 arch/arm/Makefile 中被指定为:head-y := arch/arm/cpu/$(CPU)/start.o
u-boot-init= arch/arm/cpu/armv7/start.o
u-boot-main是uboot 所有子目录下 build-in.o 的集合

以上的规则就相当于将以 u-boot.lds 为链接脚本,将 arch/arm/cpu/armv7/start.o 和各个子目录 下的 built-in.o 链接在一起生成 u-boot。

三、总结

make xxx_defconfig:用于配置 uboot,这个命令最主要的目的就是生成.config 文件。

make:用于编译 uboot,这个命令的主要工作就是生成二进制的 u-boot.bin 文件和其他的一 些与 uboot 有关的文件,比如 u-boot.imx 等等。 

 

以上是关于正点原子imx6ullUBOOT顶层Makefile学习笔记的主要内容,如果未能解决你的问题,请参考以下文章

正点原子开发板STM32 PWM输出实验 改变LED0为LED1不亮

正点原子探索者STM32F407开发板/战舰STm32开发板/miniSTM32开发板资料下载

正点原子Linux移植Qt,正点原子I.MX6U Qt综合例程源码

正点原子FPGA连载第九章按键控制LED灯实验 -摘自正点原子新起点之FPGA开发指南_V2.1

正点原子FPGA连载第三十六章双路高速DA实验 -摘自正点原子新起点之FPGA开发指南_V2.1

Linux系统移植:正点原子 U-Boot 移植