i.MX6ULL系统移植:uboot移植7 - make xxx_defconfig总结

一、常用配置命令

当前 uboot 的配置已经完全变成 Linux 内核的配置形式了,完全可以按照 Linux 内核分析方法分析 uboot。

ubootLinux代码配置项由 Kconfig 来完成的,关于 Kconfig 语法,可参见:linux/Documentation/kbuild/kconfig-language.txt

编译时,进行配置目的根据需求选择功能以及编译生成方式类型(模式或包含在内核中)。

配置项操作可以由如下命令中的其中一条来完成:

  • make config:这个要求用户手动选择所有配置项配置完成后生成 .config 文件。
  • make menuconfig:显示以curses的图形配置菜单,当已有 .config 文件存在时,它会根据 .config 文件设定默认项。若不存在 .config 文件,则根据各级 Kconfig 文件来设定菜单项。完成配置后,生成.config文件。
  • make oldconfig:与 make menuconfig 相同,区别在于这个没有图形界面,当已有 .config 文件存在时,它根据.config文件设定默认项,若 kconfig 有新配置项时,会提示你进行选择;若不存在 .config 文件,则根据各级 Kconfig 文件来设定菜单项。完成配置后,生成 .config 文件。
  • make xx_defconfig: 一般源码中都有不同硬件平台的**默认配置文件,**你也可以制做自己的默认配置文件,当这个命令执行时,它会根据 kconfig 及 xx_defconfig 来生成 .config 文件。

执行完其中一条 config 命令后,会生成 .config 及 autoconf 文件,autoconf 是根据配置项生成相应宏定义供 makefile 使用,当执行 make 命令时,就会根据 autoconf 定义的宏及 makefile 去编译源码

二、uboot编译步骤

u-boot的编译跟kernel编译一样,分两步执行:

1、第一步:配置,执行make xxx_defconfig进行各项配置,生成.config文件 。

2、第二步:编译,执行make进行编译,生成可执行的二进制文件u-boot.binu-boot.elf

三、构建系统所支持的目标

make targets,targets 就是我们前述的那些命令,我们可以通过 make help 打印出来内核构建系统所支持的目标完整列表

如下所示,是 make help 所打印的所有目标:

onlylove@ubuntu:~/linux/uboot/alientek_uboot$ make help
Cleaning targets:
  clean		  - Remove most generated files but keep the config(清除大多数生成的文件,但是保留配置)
  mrproper	  - Remove all generated files + config + various backup files(清除所有生成的文件、配置文件和各种备份文件)
  distclean	  - mrproper + remove editor backup and patch files(此项就是 mrproper 的升级版本,多加了清除备份和补丁文件)

Configuration targets:
  config	  - Update current config utilising a line-oriented program(利用命令行更新当前配置)
  nconfig         - Update current config utilising a ncurses menu based program(使用基于ncurses菜单的程序更新当前配置)
  menuconfig	  - Update current config utilising a menu based program(利用菜单程序更新当前配置)
  xconfig	  - Update current config utilising a QT based front-end(利用基于Qt的前端更新当前配置)
  gconfig	  - Update current config utilising a GTK based front-end(利用基于GTK +的前端更新当前配置)
  oldconfig	  - Update current config utilising a provided .config as base(使用提供的.config作为基础更新当前配置)
  localmodconfig  - Update current config disabling modules not loaded(更新当前配置禁用未加载的模块)
  localyesconfig  - Update current config converting local mods to core(更新当前配置将本地mods转换为core)
  silentoldconfig - Same as oldconfig, but quietly, additionally update deps(与oldconfig相同,但是安静地更新deps)
  defconfig	  - New config with default from ARCH supplied defconfig(来自ARCH的默认配置提供了defconfig)
  savedefconfig   - Save current config as ./defconfig (minimal config)(保存当前配置为./defconfig(最小配置))
  allnoconfig	  - New config where all options are answered with no(新的配置,所有选项的答案都是no)
  allyesconfig	  - New config where all options are accepted with yes(新的配置,所有选项的答案都是yes)
  allmodconfig	  - New config selecting modules when possible(新的配置,尽可能的选择模块)
  alldefconfig    - New config with all symbols set to default(将所有符号设置为默认值的新配置)
  randconfig	  - New config with random answer to all options(对所有选项进行随机答案的新配置)
  listnewconfig   - List new options(列出新选项)
  olddefconfig	  - Same as silentoldconfig but sets new symbols to their default value(与 silentoldconfig 相同,但是对默认值设置新的符号)

Other generic targets:
  all		  - Build all necessary images depending on configuration(根据配置构建所有必要的镜像)
* u-boot	  - Build the bare u-boot(构建空的 uboot)
  dir/            - Build all files in dir and below(在dir和子目录下构建所有文件)
  dir/file.[oisS] - Build specified target only(仅构建指定的目标)
  dir/file.lst    - Build specified mixed source/assembly target only(仅构建指定的混合源/汇编目标)
                    (requires a recent binutils and recent build (System.map))(需要最新的binutils和最新的版本(System.map))
  tags/ctags	  - Generate ctags file for editors(生成 ctags 索引文件)
  etags		  - Generate etags file for editors(生成 etags 索引文件)
  cscope	  - Generate cscope index(生成 cscope 索引)
  ubootrelease	  - Output the release version string (use with make -s)(输出发行版本字符串(需要用 make -s))
  ubootversion	  - Output the version stored in Makefile (use with make -s)(输出保存在 Makefile 中的版本(需要用 make -s))

Static analysers
  checkstack      - Generate a list of stack hogs(生成堆栈列表)

Documentation targets:
 U-Boot bootloader internal documentation in different formats:
  htmldocs        - HTML
  pdfdocs         - PDF
  psdocs          - Postscript
  xmldocs         - XML DocBook
  mandocs         - man pages
  installmandocs  - install man pages generated by mandocs
  cleandocs       - clean all generated DocBook files

  make V=0|1 [targets] 0 => quiet build (default), 1 => verbose build
  make V=2   [targets] 2 => give reason for rebuild of target
  make O=dir [targets] Locate all output files in "dir", including .config
  make C=1   [targets] Check all c source with $CHECK (sparse by default)
  make C=2   [targets] Force check of all c source with $CHECK
  make RECORDMCOUNT_WARN=1 [targets] Warn about ignored mcount sections
  make W=n   [targets] Enable extra gcc checks, n=1,2,3 where
		1: warnings which may be relevant and do not occur too often
		2: warnings which occur quite often but may still be relevant
		3: more obscure warnings, can most likely be ignored
		Multiple levels can be combined with W=12 or W=123

Execute "make" or "make all" to build all targets marked with [*] 
For further info see the ./README file
onlylove@ubuntu:~/linux/uboot/alientek_uboot$

四、构建系统的文件

1、文件介绍

./Document/kbuild/makefiles.txt 中有详细介绍。

Makefiles 有 5 个部分:

  • Makefile顶层 Makefile,提供针对各种目标的接口,一般和实现无关。当我们要针对某个目标进行分析时,作为起点,总是尝试在此文件中找到对应的目标定义,然后沿着该定义深入挖掘。
  • .configuboot 配置文件,如果是内核,就是内核的配置文件,在配置 uboot时候生成,所有的 Makefile 文件(包括顶层目录及各级子目录)都是根据 .config 来决定使用哪些文件
  • arch/$(ARCH)/Makefile平台相关 Makefile,提供针对不同架构目标变量规则定义。文件位置比较固定
  • scripts/Makefile.:Makefile 共用的通用规则*、脚本等。
  • kbuild Makefiles:各级子目录下的 Makefile,相对简单被上一层 Makefile 调用来编译当前目录下的文件。

顶层 Makefiles 读取从uboot 配置程序中生成的 .config 文件。

2、文件关联

在上述的所有文件中,除了顶层的 Makefile,其他文件都或直接、或间接的和 它相关联。这些关联可以分为两类

1、直接包含:在一个文件中,用 include 来包含另外的文件

2、间接包含:使用 make -f 来调用,-f 是使用不同的 makefile 文件来进行 make 的选项。

五、make xxx_defconfig 命令执行分析

使用 NXP 官方提供uboot,使用 iMX6ULL 芯片进行测试,执行命令:make V=1 mx6ull_14x14_lq_emmc_defconfig

onlylove@ubuntu:~/linux/uboot/nxp_uboot/uboot-imx-rel_imx_4.1.15_2.1.0_ga$ make V=1 mx6ull_14x14_lq_emmc_defconfig

# 生成了 scripts/basic/fixdep 工具
make -f ./scripts/Makefile.build obj=scripts/basic
  cc -Wp,-MD,scripts/basic/.fixdep.d -Wall -Wstrict-prototypes -O2 -fomit-frame-pointer     -o scripts/basic/fixdep scripts/basic/fixdep.c  
rm -f .tmp_quiet_recordmcount

# 生成了 scripts/kconfig/conf 工具
make -f ./scripts/Makefile.build obj=scripts/kconfig mx6ull_14x14_lq_emmc_defconfig
  cc -Wp,-MD,scripts/kconfig/.conf.o.d -Wall -Wstrict-prototypes -O2 -fomit-frame-pointer   -D_DEFAULT_SOURCE -D_XOPEN_SOURCE=600 -DCURSES_LOC="" -DNCURSES_WIDECHAR=1 -DLOCALE   -c -o scripts/kconfig/conf.o scripts/kconfig/conf.c
  cat scripts/kconfig/zconf.tab.c_shipped > scripts/kconfig/zconf.tab.c
  cat scripts/kconfig/zconf.lex.c_shipped > scripts/kconfig/zconf.lex.c
  cat scripts/kconfig/zconf.hash.c_shipped > scripts/kconfig/zconf.hash.c
  cc -Wp,-MD,scripts/kconfig/.zconf.tab.o.d -Wall -Wstrict-prototypes -O2 -fomit-frame-pointer   -D_DEFAULT_SOURCE -D_XOPEN_SOURCE=600 -DCURSES_LOC="" -DNCURSES_WIDECHAR=1 -DLOCALE  -Iscripts/kconfig -c -o scripts/kconfig/zconf.tab.o scripts/kconfig/zconf.tab.c

# 执行 scripts/kconfig/conf 工具 生成.config
scripts/kconfig/conf  --defconfig=arch/../configs/mx6ull_14x14_lq_emmc_defconfig Kconfig
#
# configuration written to .config
#

通过以上输出日志,可以确定 make xxx_defconfig 的执行主要分成三个部分

1、执行 make -f ./scripts/Makefile.build obj=scripts/basic,编译生成 scripts/basic/fixdep 工具。

2、执行 make -f ./scripts/Makefile.build obj=scripts/kconfig mx6ull_14x14_lq_emmc_defconfig, 编译生成 scripts/kconfig/conf 工具。

3、执行 scripts/kconfig/conf --defconfig=arch/../configs/mx6ull_14x14_lq_emmc_defconfig Kconfig ,生成最终的 .config 配置文件。

六、顶层make defconfig规则

make xxx_defconfig 的执行主要分成三个部分:

1、执行 make -f ./scripts/Makefile.build obj=scripts/basic,编译生成 scripts/basic/fixdep 工具。

2、执行 make -f ./scripts/Makefile.build obj=scripts/kconfig mx6ull_14x14_lq_emmc_defconfig, 编译生成 scripts/kconfig/conf 工具。

3、执行 scripts/kconfig/conf --defconfig=arch/../configs/mx6ull_14x14_lq_emmc_defconfig Kconfig ,生成最终的 .config 配置文件。

执行 make xxx_defconfig命令时,u-boot 根目录下的 Makefile 中有唯一的规则匹配目标:

ifeq ($(config-targets),1)
# ===========================================================================
# *config targets only - make sure prerequisites are updated, and descend
# in scripts/kconfig to make the *config target

KBUILD_DEFCONFIG := sandbox_defconfig
export KBUILD_DEFCONFIG KBUILD_KCONFIG

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

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

注释意思为,仅限 *config 目标,确保先决条件已经更新,并在 scripts/kconfig 下创建 *config 目标。

上面有两个变量 config 和 %config,% 符号为通配符,对应所有的 xxxconfig 目标。我们的 make xxx_defconfig 就对应 %config,我们并没有执行 make config 命令。

1、分析 %config 执行条件

KBUILD_EXTMODE 赋值代码:

# Use make M=dir to specify directory of external module to build
# 使用make M=dir指定要构建的外部模块的目录
# Old syntax make ... SUBDIRS=$PWD is still supported
# 旧语法make…SUBDIRS=$PWD仍然支持
# Setting the environment variable KBUILD_EXTMOD take precedence
# 优先设置环境变量KBUILD EXTMOD
ifdef SUBDIRS
  KBUILD_EXTMOD ?= $(SUBDIRS)
endif

ifeq ("$(origin M)", "command line")
  KBUILD_EXTMOD := $(M)
endif

由注释可以知道,SUBDIRS 这个变量是通过执行 make 的时候传进来的,我们并没有执行此项所以未定义SUBDIRS,第一个分支不会去走。第二个 if 语句为 ifeq 语句,这里使用 origin 函数。

  • origin 函数说明
 $(origin <variable>)
 函数名称:  获取变量信息— origin。
 函数功能:  获取此变量(参数)相关的信息,告诉我们这个变量的出处(定义方式)。
 返回值:

ifeq ("$(origin M)", "command line") 语句含义,如果make传入的命令行变量存在且是M,那么,变量KBUILD_EXTMOD变为变量M的值。

第一阶段中我们并没有传入 M 值,则 KBUILD_EXTMOD 值为空。

# To make sure we do not include .config for any of the *config targets
# catch them early, and hand them over to scripts/kconfig/Makefile
# It is allowed to specify more targets when calling make, including
# mixing *config targets and build targets.
# 为了确保我们不为任何配置目标包含.config,尽早捕获它们,
# 并将它们交给scripts/kconfig/Makefile。
# 当调用make时,允许指定更多的目标,包括混合配置目标和构建目标。
# For example 'make oldconfig all'. 例如'make oldconfig all'
# Detect when mixed targets is specified, and make a second invocation
# of make so .config is not included in this case either (for *config).
# 检测何时指定了混合目标,并进行第二次make so调用,在这种情况下也不包括.config(对于config)。

version_h := include/generated/version_autogenerated.h
timestamp_h := include/generated/timestamp_autogenerated.h

no-dot-config-targets := clean clobber mrproper distclean \
			 help %docs check% coccicheck \
			 ubootversion backup

config-targets := 0
mixed-targets  := 0
dot-config     := 1

ifneq ($(filter $(no-dot-config-targets), $(MAKECMDGOALS)),)
	ifeq ($(filter-out $(no-dot-config-targets), $(MAKECMDGOALS)),)
		dot-config := 0
	endif
endif

ifeq ($(KBUILD_EXTMOD),)
        ifneq ($(filter config %config,$(MAKECMDGOALS)),)
                config-targets := 1
                ifneq ($(words $(MAKECMDGOALS)),1)
                        mixed-targets := 1
                endif
        endif
endif
  • version_h:版本号文件,此文件是自动生成的。
  • timestamp_h:时间戳文件,此文件是自动生成的。
  • no-dot-config-targets:指代的是那些和 .config 没有关系的目标
  • config-targets:配置目标初始值设置为0
  • mixed-targets:混合目标初始值设置为0
  • dot-config:初始值设置为1。
  • MAKECMDGOALS:make 在执行时会设置一个特殊变量 – “MAKECMDGOALS” ,该变量记录命令行参数指定的终极目标列表,没有通过参数指定终极目标时此变量为空。该变量仅限于用在特殊场合(比如判断),在 Makefile 中最好不要对它进行重新定义。执行 make xxx_defconfig 的时候,MAKECMDGOALS 变量的值就为 xxx_defconfig。
  • filter 函数说明
 $(filter PATTERN…,TEXT)
 函数名称:  过滤函数— filter。
 函数功能:  过滤掉字串“ TEXT”中所有不符合模式“ PATTERN”的单词,保留所
         有符合此模式的单词。可以使用多个模式。模式中一般需要包含模式字
        符“ %”。存在多个模式时,模式表达式之间使用空格分割。
 返回值:空格分割的“ TEXT”字串中所有符合模式“ PATTERN”的字串。
 函数说明:“ filter”函数可以用来去除一个变量中的某些字符串
  • filter-out 函数说明
 $(filter-out PATTERN...,TEXT)
 函数名称:  反过滤函数— filter-out
 函数功能:  和“ filter”函数实现的功能相反。过滤掉字串“ TEXT”中所有符合模式“ PATTERN”的单词,保留所有不符合此模式的单词。
       可以有多个模式。存在多个模式时,模式表达式之间使用空格分割
 返回值:  空格分割的“ TEXT”字串中所有不符合模式“ PATTERN”的字串。
 函数说明:  “ filter-out”函数也可以用来去除一个变量中的某些字符串,(实现和“ filter”函数相反)
  • words 函数说明
 $(words TEXT)
 函数名称:  统计单词数目函数 — words
 函数功能:  计算字串 “TEXT” 中单词数目。
 返回值:    “TEXT” 中单词数。
 函数说明:  

代码执行过程分析

1、ifneq ($(filter $(no-dot-config-targets), $(MAKECMDGOALS)),) 函数含义为,如果 过滤掉 MAKECMDGOALS 不符合 no-dot-config-targets 后结果不为空,则执行分支语句。很显然过滤后为空,则不执行分支语句,dot-config 依然 值为1。

2、ifeq ($(KBUILD_EXTMOD),) 含义为,如果 KBUILD_EXTMOD 为空,执行分支语句。因为 KBUILD_EXTMOD 为空,因此分支语句被执行。

3、 ifneq ($(filter config %config,$(MAKECMDGOALS)),)含义为,滤掉 MAKECMDGOALS 不符合 config 和 %config 模式的字符串,因此返回值为 xxx_defconfig,xxx_defconfig 再与 空进行比较,if 语句为 ifneq ,很显然, filter 语句不为空,与空进行比较,满足 ifneq 执行语句。

4、config-targets := 1 含义为将 config-targets 重新赋值为 1。

5、ifneq ($(words $(MAKECMDGOALS)),1) 含义为,通过统计 MAKECMDGOALS 中单词数,返回 1。ifneq 判断 MAKECMDGOALS 中单词数为1,不执行分支语句。mixed-targets 的值依旧为 0。

6、分析结束后,变量值如下:

MAKECMDGOALS = xxx_defconfig
KBUILD_EXTMOD =
version_h := include/generated/version_autogenerated.h
timestamp_h := include/generated/timestamp_autogenerated.h
no-dot-config-targets := clean clobber mrproper distclean help %docs check% coccicheck ubootversion backup tests
config-targets := 1
mixed-targets := 0
dot-config := 1

2、%config分析

因为 config-targets 的值等于1,因此 %config 规则可以执行。

ifeq ($(config-targets),1)
# ===========================================================================
# *config targets only - make sure prerequisites are updated, and descend
# in scripts/kconfig to make the *config target

KBUILD_DEFCONFIG := sandbox_defconfig
export KBUILD_DEFCONFIG KBUILD_KCONFIG

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

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

else
	# 不会执行,因此省略
endif

1、定义2个环境变量,KBUILD_DEFCONFIG := sandbox_defconfigKBUILD_KCONFIG为空。

2、config 没有匹配,不会执行。

3、%config 依赖scripts_basic outputmakefile FORCE

1、FORCE

PHONY += FORCE
FORCE:

FORCE被定义为一个空目标。如果一个目标添加 FORCE依赖,每次编译都会去先去执行 FORCE(实际上什么都不做),然后运行命令更新目标,这样就能确保目标每次都会被更新。

2、scripts_basic

# ===========================================================================
# Rules shared between *config targets and build targets
# 在配置目标和构建目标之间共享的规则

# Basic helpers built in scripts/
# 脚本中内置的基本帮助程序
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 ;

Q = @MAKE = makebuild 变量的定义在 scripts/Kbuild.include 文件中。

Makefile 包含 scripts/Kbuild.include 文件,详细内容如下:

# We need some generic definitions (do not try to remake the file).
# 我们需要一些通用定义(不要尝试重新创建文件)。
scripts/Kbuild.include: ;
include scripts/Kbuild.include

scripts/Kbuild.include 文件中包含如下内容:

###
# Shorthand for $(Q)$(MAKE) -f scripts/Makefile.build obj=
# Usage:
# $(Q)$(MAKE) $(build)=dir
build := -f $(srctree)/scripts/Makefile.build obj

srctree 定义在主 Makefile 中:

ifeq ($(KBUILD_SRC),)
        # building in the source tree 在源代码树中构建
        srctree := .
else
        ifeq ($(KBUILD_SRC)/,$(dir $(CURDIR)))
                # building in a subdirectory of the source tree 在源树的子目录中构建
                srctree := ..
        else
                srctree := $(KBUILD_SRC)
        endif
endif

KBUILD_SRC:make 时使用 O 输入源码构建目录,在执行时没有传入,因此为空。因此执行 srctree := . 语句。

主 Makefile 中 scripts_basic 的展开为

scripts_basic:
	# 根据传入的 obj 参数显示的执行 ./scripts/Makefile.build 文件
     make -f ./scripts/Makefile.build obj=scripts/basic  
     rm -f .tmp_quiet_recordmcount

3、outputmakefile

PHONY += outputmakefile
# outputmakefile generates a Makefile in the output directory, if using a
# separate output directory. This allows convenient use of make in the
# output directory.
# 如果使用单独的输出目录,
# 则outputmakefile在输出目录中生成一个Makefile。
# 这允许在输出目录中方便地使用make。
outputmakefile:
ifneq ($(KBUILD_SRC),)
	$(Q)ln -fsn $(srctree) source
	$(Q)$(CONFIG_SHELL) $(srctree)/scripts/mkmakefile \
	    $(srctree) $(objtree) $(VERSION) $(PATCHLEVEL)
endif

KBUILD_SRC 为空,所以ifneq 中的语句不会执行。 outputmakefile 为空。

4、%config

%config 展开后,规则如下。

make -f ./scripts/Makefile.build obj=scripts/kconfig xxx_defconfig

3、%config总结

1、变量

MAKECMDGOALS = xxx_defconfig
KBUILD_EXTMOD =
version_h := include/generated/version_autogenerated.h
timestamp_h := include/generated/timestamp_autogenerated.h
no-dot-config-targets := clean clobber mrproper distclean help %docs check% coccicheck ubootversion backup tests
config-targets := 1
mixed-targets := 0
dot-config := 1
KBUILD_SRC =
build := -f ./scripts/Makefile.build obj

2、环境变量

KBUILD_DEFCONFIG := sandbox_defconfig
KBUILD_KCONFIG =

3、%config 规则执行命令

1、make -f ./scripts/Makefile.build obj=scripts/basic(scripts_basic规则中执行)。

2、rm -f .tmp_quiet_recordmcount(scripts_basic规则中执行)。

3、make -f ./scripts/Makefile.build obj=scripts/kconfig xxx_defconfig(%config规则中执行)。

七、./scripts/Makefile.build分析

1、make -f ./scripts/Makefile.build obj=scripts/basic

make -f scripts/Makefile.build obj=scripts/basic 命令由于没有指定目标,所以会在 script/Makefile.build 中处理默认目标__build:

# 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)
	@:

在 scripts/Makefile.build 中会包含scripts/basic 目录下的 Kbuild/Makefile,,所以该make命令的实际效果是去编译出 scripts/basic 目录下的三个 host program,也就是 fixdep docproc和hash。

# The filename Kbuild has precedence over Makefile
# 文件Kbuild优先于Makefile
kbuild-dir := $(if $(filter /%,$(src)),$(src),$(srctree)/$(src))
kbuild-file := $(if $(wildcard $(kbuild-dir)/Kbuild),$(kbuild-dir)/Kbuild,$(kbuild-dir)/Makefile)
include $(kbuild-file)

什么是host program?一般认为是和内核无关,但是要在编译过程中使用的工具程序。关于这些程序的编译,参考 scripts/Makefile.host 文件,以及 Documentation/kbuild/makefile.txt 文件中关于 host program 的这一节。

scripts/basic 文件夹中的 Makefile 内容如下

hostprogs-y	:= fixdep
always		:= $(hostprogs-y)

# fixdep is needed to compile other host programs
$(addprefix $(obj)/,$(filter-out fixdep,$(always))): $(obj)/fixdep

2、make -f ./scripts/Makefile.build obj=scripts/kconfig xxx_defconfig

文件 scripts/Makefile.build 会包含 obj 变量所指代目录内的 Makefile 的,在这里就是 script/kconfig/Makefile

%_defconfig: $(obj)/conf
	$(Q)$< $(silent) --defconfig=arch/$(SRCARCH)/configs/$@ $(Kconfig)

# Added for U-Boot (backward compatibility)
%_config: %_defconfig
	@:

在这里,xxx_defconfig 需要依赖于同目录下的conf程序。这其实就是 Linux 内核进行Kconfig操作的主程序之一了,类似的还有mconf,qconf和gconf等。他们其实都是 host program。关于它们是如何被编译出来的,还请参见 scripts/kconfig/Makefile 文件,主要是借助于 bison,flex 和 gperf 三个工具来生成c源程序文件,之后再编译出来的。

kconfig 的定义在 scripts/kconfig 文件夹中的 Makefile 内容中

ifdef KBUILD_KCONFIG
Kconfig := $(KBUILD_KCONFIG)
else
Kconfig := Kconfig
endif

ifeq ($(quiet),silent_)
silent := -s
endif

由于变量 KBUILD_KCONFIGarm架构Makefile中没有被定义,所以 Kconfig 被定义成 arch/arm/kconfig。silent 是确定是否执行静态编译。所以这个目标的规则简化成:

$(obj)/conf -s --defconfig=arch/arm/configs/xxx_defconfig arch/arm/Kconfig

这个命令就是读取并解析以 arch/arm/Kconfig 为首的内核功能选项配置文件,并将文件 arch/arm/configs/xxx_defconfig 所设置的默认值分配给对应的所有选项,最终生成配置文件 .config。

八、总结

  • 在 uboot 或内核开始真正编译之前,构建系统会以 .config 文件为蓝本生成 include/config/auto.conf 文件,这个文件的格式和 .config类似,这个文件会在顶层以及 scripts/Makefile.build 文件中被直接包含进来,所以这些变量其实就成了 GNU Make 的变量
  • 而uboot 或 内核各子目录中的 Kbuild/Makefile 就可以使用这些变量的定义,来决定是否将该目录下对应的代码功能直接编译到内核里面(这些变量取值为"y")、编译成模块(取值为"m")或者干脆不进行编译(取值为"空")。
  • 可以想见,如果选择不编译,那出来的Linux内核就不会有对应的功能。
    配置的时候,配置工具首先会解析架构平台目录下的 Kconfig,这就是所谓和平台相关的主Kconfig。主Kconfig文件会包含其他目录的Kcofnig文件,而其他目录的Kconfig又会包含其他各子目录的 Kconfig。如此形成一个树型结构

你可能感兴趣的:(i.MX6ULL,uboot)