U-Boot作为遵循GPL条款的开放源码项目,目前已经占据了嵌入式Linux的大部分应用场合。内核是通过Bootloader来引导的,Bootloader最常用的是U-Boot。2015以后发布的U-Boot版本开始参考Linux内核的Kconfig结构,发生了较大的变化。
查看U-Boot的readme可以看到变化:
Previously, all configuration was done by hand, which involvedcreating symbolic links and editing configuration files manually. Morerecently, U-Boot has added the Kbuild infrastructure used by the Linux kernel,allowingyou to use the "make menuconfig" command to configure your build.
NPX官方BSP下载地址:http://git.freescale.com/git/cgit.cgi/imx/
编译imx6的U-Boot分如下两步:
第一步:make imx6ul_14x14_nand_defconfig
第二部:make
第一步是配置命令,本文以IMX6硬件为例,主要分析uboot移植第一步配置命令具体都做了那些事,以及结果是什么。
(1)Makefile
根据配置命令make imx6ul_14x14_nand_defconfig,首先查看Makefile文件,哪里与*_defconfig相关,发现如下代码:
%config: scripts_basic outputmakefile FORCE
$(Q)$(MAKE)$(build)=scripts/kconfig $@
即make imx6ul_14x14_nand_defconfig会匹配到这里。
(2)目标与依赖
此时目标命令$(Q)$(MAKE) $(build)=scripts/kconfig$@,产生了三个依赖scripts_basic、outputmakefile、FORCE。
在Makefile依次查找这三个依赖:
依赖条件1:scripts_basic
scripts_basic:
$(Q)$(MAKE)$(build)=scripts/basic
$(Q)rm-f .tmp_quiet_recordmcount
依赖条件2:outputmakefile(不执行)
# outputmakefile generates a Makefile inthe output directory, if using a
# separate output directory. This allowsconvenient use of make in the
# output directory.
outputmakefile:
ifneq ($(KBUILD_SRC),)
$(Q)ln-fsn $(srctree) source
$(Q)$(CONFIG_SHELL)$(srctree)/scripts/mkmakefile \
$(srctree) $(objtree) $(VERSION)$(PATCHLEVEL)
Endif
KBUILD_SRC为空,此依赖条件并不执行。
依赖条件3:FORCE(不执行什么)
PHONY += FORCE
FORCE:
其中的变量:
$(srctree)=.(为源码绝对路径)
$(build)
定义在:scripts/Kbuild.include
build := -f$(srctree)/scripts/Makefile.build obj
展开后:
build := -f ./scripts/Makefile.buildobj
$(Q)在根Makefile最上面定义,值为空或者@,@表示不显示源命令。如下:
ifeq ($(KBUILD_VERBOSE),1)
quiet =
Q =
else
quiet=quiet_
Q =@
endif
$(MAKE) = make
$(CONFIG_SHELL) = /bin/sh
$@ = %config
将这些变量带入依赖表达式中:
所以依赖条件1变为:
scripts_basic:
@make -f scripts/Makefile.build obj=scripts/basic
@rm -f.tmp_quiet_recordmcount
此时目标变成:
imx6ul_14x14_nand_defconfig:scripts_basic
@make –f ./scripts/Makefile.build obj=scripts/kconfig imx6ul_14x14_nand_defconfig
接下来分别是依赖和主目标调用执行scripts/Makefile.build
第一次:
make -f scripts/Makefile.build obj=scripts/basic
将obj=scripts/basic传入Makefile.build。
Makefile.build开头会接收传入的obj变量并赋给src。
prefix := tpl
src := $(patsubst $(prefix)/%,%,$(obj))
ifeq ($(obj),$(src))
prefix := spl
src := $(patsubst $(prefix)/%,%,$(obj))
ifeq ($(obj),$(src))
prefix := .
endif
endif
然后将src下的makefile包含进来,最终src= scripts/basic下的makefile内容被编译。(具体编译结果后面分析)
同理:
imx6ul_14x14_nand_defconfig:scripts_basic
@make –f ./scripts/Makefile.build obj=scripts/kconfig imx6ul_14x14_nand_defconfig
结果是将scripts/kconfig目录下makefile文件的中目标被编译。即:
scripts/kconfig/Makefile中的%_defconfig被匹配:
%_defconfig: scripts/kconfig/conf
$(Q)$<$(silent) --defconfig=arch/$(SRCARCH)/configs/$@ $(Kconfig)
展开后:
imx6ul_14x14_nand_defconfig:
$(Q)scripts/kconfig/conf --defconfig=arch/../configs/ imx6ul_14x14_nand_defconfig Kconfig
scripts/kconfig /conf:读取Kconfig及imx6ul_14x14_nand_defconfig输出到.config。上述编译产生了一些应用程序:
查看scripts\basic目录下的makefile 编译了fixdep.c,用于解决依赖的问题:
# Makefile.basic lists the most basic programs used during the build process.
# The programs listed herein are what are needed to do the basic stuff,
# such as fix file dependencies.
# This initial step is needed to avoid files to be recompiled
# when kernel configuration changes (which is what happens when
# .config is included by main Makefile.
# ---------------------------------------------------------------------------
# fixdep: Used to generate dependency information during build process
#
# SPDX-License-Identifier: GPL-2.0
#
hostprogs-y := fixdep
always := $(hostprogs-y)
# fixdep is needed to compile other host programs
$(addprefix $(obj)/,$(filter-out fixdep,$(always))): $(obj)/fixdep