【嵌入式移植】5、U-Boot源码分析2—make nanopi_neo2_defconfig

U-Boot源码分析2—make nanopi_neo2_defconfig

  • 1 概述
  • 2 nanopi_neo2_defconfig
  • 3 编译过程分析
    • 3.1 编译目标
    • 3.2 scripts_basic
    • 3.2.1 prefix src定义
    • 3.2.2 PHONY
    • 3.2.3 __build
    • 3.2.4 fixdep
    • 3.3 obj=scripts/kconfig

1 概述

上一章中,对Makefile相关源码进行了初步分析,这里结合编译过程具体分析其执行过程。

2 nanopi_neo2_defconfig

nanopi_neo2_defconfig文件位于./config/目录下,内容如下

CONFIG_ARM=y
CONFIG_ARCH_SUNXI=y
CONFIG_MACH_SUN50I_H5=y
CONFIG_DRAM_CLK=672
CONFIG_DRAM_ZQ=3881977
CONFIG_DEFAULT_DEVICE_TREE="sun50i-h5-nanopi-neo2"
# CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
CONFIG_SPL=y
# CONFIG_CMD_FLASH is not set
# CONFIG_CMD_FPGA is not set
# CONFIG_SPL_DOS_PARTITION is not set
# CONFIG_SPL_ISO_PARTITION is not set
# CONFIG_SPL_EFI_PARTITION is not set
CONFIG_SUN8I_EMAC=y
CONFIG_USB_EHCI_HCD=y
CONFIG_SYS_USB_EVENT_POLL_VIA_INT_QUEUE=y

3 编译过程分析

首先通过make nanopi_neo2_defconfig -n命令,-n表示仅输出执行过程中的命令序列,而不真正执行

make -f ./scripts/Makefile.build obj=scripts/basic
set -e;  echo '  HOSTCC  scripts/basic/fixdep'; cc -Wp,-MD,scripts/basic/.fixdep.d -Wall -Wstrict-prototypes -O2 -fomit-frame-pointer      -o scripts/basic/fixdep scripts/basic/fixdep.c  ; scripts/basic/fixdep scripts/basic/.fixdep.d scripts/basic/fixdep 'cc -Wp,-MD,scripts/basic/.fixdep.d -Wall -Wstrict-prototypes -O2 -fomit-frame-pointer      -o scripts/basic/fixdep scripts/basic/fixdep.c  ' > scripts/basic/.fixdep.tmp; rm -f scripts/basic/.fixdep.d; mv -f scripts/basic/.fixdep.tmp scripts/basic/.fixdep.cmd
:
rm -f .tmp_quiet_recordmcount
make -f ./scripts/Makefile.build obj=scripts/kconfig nanopi_neo2_defconfig
set -e;  echo '  HOSTCC  scripts/kconfig/conf.o'; 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; scripts/basic/fixdep scripts/kconfig/.conf.o.d scripts/kconfig/conf.o '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' > scripts/kconfig/.conf.o.tmp; rm -f scripts/kconfig/.conf.o.d; mv -f scripts/kconfig/.conf.o.tmp scripts/kconfig/.conf.o.cmd
echo '  SHIPPED scripts/kconfig/zconf.tab.c'; cat scripts/kconfig/zconf.tab.c_shipped > scripts/kconfig/zconf.tab.c
echo '  SHIPPED scripts/kconfig/zconf.lex.c'; cat scripts/kconfig/zconf.lex.c_shipped > scripts/kconfig/zconf.lex.c
echo '  SHIPPED scripts/kconfig/zconf.hash.c'; cat scripts/kconfig/zconf.hash.c_shipped > scripts/kconfig/zconf.hash.c
set -e;  echo '  HOSTCC  scripts/kconfig/zconf.tab.o'; 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/basic/fixdep scripts/kconfig/.zconf.tab.o.d scripts/kconfig/zconf.tab.o '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/.zconf.tab.o.tmp; rm -f scripts/kconfig/.zconf.tab.o.d; mv -f scripts/kconfig/.zconf.tab.o.tmp scripts/kconfig/.zconf.tab.o.cmd
set -e;  echo '  HOSTLD  scripts/kconfig/conf'; cc  -o scripts/kconfig/conf scripts/kconfig/conf.o scripts/kconfig/zconf.tab.o  ; printf '%s\n' 'cmd_scripts/kconfig/conf := cc  -o scripts/kconfig/conf scripts/kconfig/conf.o scripts/kconfig/zconf.tab.o  ' > scripts/kconfig/.conf.cmd
scripts/kconfig/conf  --defconfig=arch/../configs/nanopi_neo2_defconfig Kconfig

也可以通过make nanopi_neo2_defconfig V=1命令查看编译过程中的详细输出

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
make -f ./scripts/Makefile.build obj=scripts/kconfig nanopi_neo2_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
  cc  -o scripts/kconfig/conf scripts/kconfig/conf.o scripts/kconfig/zconf.tab.o  
scripts/kconfig/conf  --defconfig=arch/../configs/nanopi_neo2_defconfig Kconfig
#
# configuration written to .config
#

下面根据上述内容,对照Makefile源码进行分析

3.1 编译目标

执行make nanopi_neo2_defconfig V=1时,编译目标为nanopi_neo2_defconfig ,即MAKECMDGOALS = nanopi_neo2_defconfig

在Makefile源码中搜索:defconfig:无相关项,搜索config:有两处匹配
请添加图片描述
对应Makefile中源码为
【嵌入式移植】5、U-Boot源码分析2—make nanopi_neo2_defconfig_第1张图片
根据上一章3.16节的分析,当执行make xxx_defconfig时,此时config-targets = 1, mixed-targets = 0, dot-config = 1,满足第467行条件 ,因此分支有效。

根据编译目标MAKECMDGOALS = nanopi_neo2_defconfig,与第478行匹配(其中%为通配符),即nanopi_neo2_defconfig依赖项为scripts_basic outputmakefile FORCE,其中FORCE在第1702行定义
【嵌入式移植】5、U-Boot源码分析2—make nanopi_neo2_defconfig_第2张图片
FORCE的依赖项与执行语句均为空,即为没有命令或者依赖的规则,这样的规则每次在执行时,目标总会被认为是最新的(更新过的),因此当它被作为其它规则的依赖时,由于FORCE总是被认为是更新过的,所以在FORCE所在的规则中定义的命令总会被执行

也就是说,由于FORCE是没有命令或者依赖的规则,而nanopi_neo2_defconfig依赖项包含FORCE,每次都会执行nanopi_neo2_defconfig规则的命令

将Makefile源码中的变量替换为其值,得到nanopi_neo2_defconfig规则的全貌(其中$@为Makefile的自动化变量,表示目前规则中所有的目标的集合)

nanopi_neo2_defconfig: scripts_basic outputmakefile FORCE
	make -f ./scripts/Makefile.build obj=scripts/kconfig nanopi_neo2_defconfig

对于依赖项outputmakefile,根据上一章分析可知为空,因此

nanopi_neo2_defconfig: scripts_basic FORCE
	make -f ./scripts/Makefile.build obj=scripts/kconfig nanopi_neo2_defconfig

3.2 scripts_basic

搜索Makefile中scripts_basic规则,仅有一处
【嵌入式移植】5、U-Boot源码分析2—make nanopi_neo2_defconfig_第3张图片
scripts_basic规则没有依赖项,其命令为(-f为指定其它文件为描述文件)

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

对应命令序列的第1行和第3行,也即编译过程中输出信息的第1行和第3行

后续对./scripts/Makefile.build文件进行分析

3.2.1 prefix src定义

第9行~17行,定义了2个变量,这里obj在执行命令时输入,为scripts/basic
【嵌入式移植】5、U-Boot源码分析2—make nanopi_neo2_defconfig_第4张图片
最终结果为

prefix = .
src = scripts/basic

3.2.2 PHONY

第19行~54行,定义PHONY等变量,并包含一些文件
【嵌入式移植】5、U-Boot源码分析2—make nanopi_neo2_defconfig_第5张图片
PHONY为第一个出现的规则,也为默认规则,实际上的默认目标为其依赖项__build,在这里__build暂时为空

第57行~59行,定义了kbuild-file并包含。
首先是kbuild-dir的赋值,这里if语句不满足条件,因此kbuild-dir的值为后半部分$(srctree)/$(src),即kbuild-dir = ./scripts/basic
./scripts/basic目录下无Kbuild文件,因此58行的if语句不满足条件,kbuild-file的值为后半部分$(kbuild-dir)/Makefile,即kbuild-file = ./scripts/basic/Makefile
第59行包含此Makefile

3.2.3 __build

查找__build,在**第116行119行**定义了依赖项和规则,116行118行为依赖项,119行为规则
请添加图片描述
这里KBUILD_BUILTINKBUILD_MODULES在顶层Makefile中定义:KBUILD_BUILTIN :=1 KBUILD_MODULES :=,因此__build规则为

__build: $(builtin-target) $(lib-target) $(extra-y) $(subdir-ym) $(always)
	@:

builtin-target在第108行~110行定义
【嵌入式移植】5、U-Boot源码分析2—make nanopi_neo2_defconfig_第6张图片
其中obj-yobj-mobj-subdir-mextra-ysubdir-ym均为空,则lib-targetbuiltin-target也为空

因此__build规则为

__build: $(always)
	@:

always./scripts/basic/Makefile(根据前面的分析,在Makefile.build的第59行使用include关键字调用量,因此在第59行会先执行此Makefile文件中的内容)中赋值为always := $(hostprogs-y),而hostprogs-y := fixdep,并增加obj的值作为前缀请添加图片描述
always = scripts/basic/fixdep,因此__build规则最终为

__build: scripts/basic/fixdep
	@:

因此__build规则也即scripts_basic规则最终结果为生成fixdep,根据注释可知,fixdep是用于编译其它的宿主机程序

3.2.4 fixdep

使用grep命令grep -rnw fixdep搜索fixdep关键字
【嵌入式移植】5、U-Boot源码分析2—make nanopi_neo2_defconfig_第7张图片
可以看到在scripts/Makefile.build文件中存在相应规则
【嵌入式移植】5、U-Boot源码分析2—make nanopi_neo2_defconfig_第8张图片
可知fixdep通过调用make-cmd函数,输入参数为cc_o_c编译而来;搜索make-cmd关键字,在scripts/Kbuild.include中有定义
请添加图片描述
【嵌入式移植】5、U-Boot源码分析2—make nanopi_neo2_defconfig_第9张图片
可知在make-cmd中,输入参数将组合成cmd_$(1),即cmd_cc_o_c;在scripts/路径下搜索cmd_cc_o_c
请添加图片描述
【嵌入式移植】5、U-Boot源码分析2—make nanopi_neo2_defconfig_第10张图片
根据前述分析可知未定义CONFIG_MODVERSIONS,因此cmd_cc_o_c命令如下,其中@$为自动化变量,表示目标集合,@<表示所有的依赖集合

cmd_cc_o_c = $(CC) $(c_flags) -c -o $@ $<

结合编译输出

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  

即使用CC命令,将scripts/basic/fixdep.c编译为scripts/basic/fixdep

另:(通过gcc -v --help可以查看所有 用法)

  • -Wp, 将逗号分隔的 传递给预处理器(preprocessor);-MD,scripts/basic/.fixdep.d生成文件关联信息,包含目标文件所依赖的所有源代码,将输出导入到.d文件里面;
  • -Wall生成所有警告信息;
  • -Wstrict-prototypesWarn about unprototyped function declarations;
  • -O0不做任何优化,这是默认的编译选项;
  • -O1优化会消耗少多的编译时间,它主要对代码的分支,常量以及表达式等进行优化;
  • -O2会尝试更多的寄存器级的优化以及指令级的优化,它会在编译期间占用更多的内存和编译时间;
  • -O3在 O2 的基础上进行更多的优化,例如使用伪寄存器网络,普通函数的内联,以及针对循环的更多优化;
  • -Os主要是对代码大小的优化,我们基本不用做更多的关心。
`-O0`不做任何优化,这是默认的编译选项;
`-Os``-O1`对程序做部分编译优化,对于大函数,优化编译占用稍微多的时间和相当大的内存。使用本项优化,编译器会尝试减小生成代码的尺寸,以及缩短执行时间,但并不执行需要占用大量编译时间的优化;
`-O2`是比 O1 更高级的选项,进行更多的优化,Gcc 将执行几乎所有的不包含时间和空间折中的优化。当设置 O2 选项时,编译器并不进行循环打开 loop unrolling 以及函数内联。与 O1 比较而言,O2 优化增加了编译时间的基础上,提高了生成代码的执行效率;
`-O3`比 O2 更进一步的进行优化,打开`-finline-functions``-fweb``-frename-registers``-funswitch-loops`优化选项,即使用伪寄存器网络,普通函数的内联,以及针对循环的更多优化

任何级别的优化都将带来代码结构的改变。例如:对分支的合并和消除,对公用子表达式的消除,对循环内 load/store 操作的替换和更改等,都将会使目标代码的执行顺序变得面目全非,导致调试信息严重不足;在 O2 优化后,编译器会对影响内存操作的执行顺序

3.3 obj=scripts/kconfig

上述分析已经执行make nanopi_neo2_defconfig所需依赖目标scripts_basic进行了分析,结果为生成fixdep工具

nanopi_neo2_defconfig: scripts_basic FORCE
	make -f ./scripts/Makefile.build obj=scripts/kconfig nanopi_neo2_defconfig

现在来看后续的命令语句

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

根据3.2.1节和3.2.2节中对./scripts/Makefile.build文件的分析,各变量取值为

obj         = scripts/kconfig
prefix      = . 
src         = scripts/kconfig
kbuild-dir  = scripts/kconfig
kbuild-file = scripts/kconfig/Makefile

第59行通过include $(kbuild-file)语句调用scripts/kconfig/Makefile,目标为nanopi_neo2_defconfig,因此在文件中查找关键字defconfig
【嵌入式移植】5、U-Boot源码分析2—make nanopi_neo2_defconfig_第11张图片
可知在第120行存在目标规则匹配
请添加图片描述
根据文件内变量取值,此规则翻译如下,其中$<表示依赖项的挨个值,这里只有一个,即scripts/kconfig/conf

nanopi_neo2_defconfig: scripts/kconfig/conf
	scripts/kconfig/conf --defconfig=arch/../configs/nanopi_neo2_defconfig Kconfig

结合编译过程的输出,可知通过如下过程,编译出所需的conf工具
conf工具主要由conf.czconf.tab.czconf.lex.czconf.hash.c几个文件编译而来;其中zconf.tab.c-Bison解析器、zconf.lex.c-flex解析器、zconf.hash.c-哈希解析器?,从名字可知为不同解析器的函数源码;main函数在conf.c中)

make -f ./scripts/Makefile.build obj=scripts/kconfig nanopi_neo2_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
  cc  -o scripts/kconfig/conf scripts/kconfig/conf.o scripts/kconfig/zconf.tab.o  

然后使用此conf工具,执行

scripts/kconfig/conf  --defconfig=arch/../configs/nanopi_neo2_defconfig Kconfig

根据conf.cmain函数,通过输入参数获取配置文件路径,然后调用conf_read函数读取文件内容,再调用conf_write,将内容写入默认的.config文件中

make nanopi_neo2_defconfig命令将生成fixdepconf两个工具,

然后根据默认的配置文件nanopi_neo2_defconfig生成U-Boot根目录下的.config文件

完结撒花✿✿ヽ(°▽°)ノ✿

你可能感兴趣的:(【嵌入式移植】,嵌入式,U-Boot,defconfig)