u-boot源码详解(2)

本文详细解释了makexxx_defconfig命令在UBOOT编译前的配置过程,涉及变量定义、目标匹配和Makefile逻辑。同时介绍了make命令如何生成二进制文件,重点在于配置文件的生成和最终目标文件的编译。
摘要由CSDN通过智能技术生成


13、make xxx_defconfig 过程
在编译 uboot 之前要使用“make xxx_defconfig”命令来配置 uboot,那么这个配置过程是如
何运行的呢?在顶层 Makefile 中有如下代码:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
第 422 行定义了变量 version_h,这变量保存版本号文件,此文件是自动生成的。文件include/generated/version_autogenerated.h 内容如图所示:版本号文件
在这里插入图片描述
第 423 行定义了变量 timestamp_h,此变量保存时间戳文件,此文件也是自动生成的。文件include/generated/timestamp_autogenerated.h 内容如图所示
在这里插入图片描述
第 425 行定义了变量 no-dot-config-targets。
第 429 行定义了变量 config-targets,初始值为 0。
第 430 行定义了变量 mixed-targets,初始值为 0。
第 431 行定义了变量 dot-config,初始值为 1。
第 433 行将 MAKECMDGOALS 中不符合 no-dot-config-targets 的部分过滤掉,剩下的如果不为空的话条件就成立。MAKECMDGOALS 是 make 的一个环境变量,这个变量会保存你所指定的终极目标列表,比如执行“make mx6ull_alientek_emmc_defconfig”,那么 MAKECMDGOALS就为 mx6ull_alientek_emmc_defconfig。很明显过滤后为空,所以条件不成立,变量 dot-config 依
旧为 1。
第439行判断KBUILD_EXTMOD是否为空,如果KBUILD_EXTMOD 为空的话条件成立,经过前面的分析,我们知道 KBUILD_EXTMOD 为空,所以条件成立。
第 440 行将 MAKECMDGOALS 中不符合“config”和“%config”的部分过滤掉,如果剩下的部分不为空条件就成立,很明显此处条件成立,变量 config-targets=1。
第 442 行统计 MAKECMDGOALS 中的单词个数,如果不为 1 的话条件成立。此处调用Makefile 中的 words 函数来统计单词个数,words 函数格式如下:
$(words
很明显,MAKECMDGOALS 的单词个数是 1 个,所以条件不成立,mixed-targets 继续为0。综上所述,这些变量值如下:
config-targets = 1
mixed-targets = 0
dot-config = 1
第 448 行如果变量 mixed-targets 为 1 的话条件成立,很明显,条件不成立。
第 465 行如果变量 config-targets 为 1 的话条件成立,很明显,条件成立,执行这个分支。
第 473 行,没有目标与之匹配,所以不执行。
第 476 行,有目标与之匹配,当输入“make xxx_defconfig”的时候就会匹配到%config 目标,目标“%config”依赖于 scripts_basic、outputmakefile 和 FORCE。FORCE 在顶层 Makefile的 1614 行有如下定义:

可以看出 FORCE 是没有规则和依赖的,所以每次都会 重新生成 FORCE。当 FORCE 作为其他目标的依赖时,由于 FORCE 总是被更新过的,因此依赖所在的规则总是会执行的。依赖 scripts_basic 和 outputmakefile 在顶层 Makefile 中的内容如下:
在这里插入图片描述
第 408 行,判断 KBUILD_SRC 是否为空,只有变量 KBUILD_SRC 不为空的时候outputmakefile 才有意义,经过我们前面的分析 KBUILD_SRC 为空,所以 outputmakefile 无效。只有 scripts_basic 是有效的。
第 396~398 行是 scripts_basic 的规则,其对应的命令用到了变量 Q、MAKE 和 build,其中:
Q=@或为空
MAKE=make

变量 build 是在 scripts/Kbuild.include 文件中有定义,定义如下:
在这里插入图片描述
可以看出 build=-f $(srctree)/scripts/Makefile.build obj,经过前面的分析
可知,变量 srctree 为”.”,因此:
build=-f ./scripts/Makefile.build obj
scripts_basic 展开以后如下:
scripts_basic:
@make -f ./scripts/Makefile.build obj=scripts/basic //也可以没有@,视配置而定
@rm -f . tmp_quiet_recordmcount //也可以没有@

scripts_basic 会调用文件./scripts/Makefile.build,这个我们后面在分析。
接着回到示例代码 31.3.13.1 中的%config 处,内容如下:
在这里插入图片描述
将命令展开就是:
@make -f ./scripts/Makefile.build obj=scripts/kconfig xxx_defconfig
同样也跟文件./scripts/Makefile.build 有关,我们后面再分析此文件。使用如下命令配置 uboot,
并观察其配置过程:
make mx6ull_14x14_ddr512_emmc_defconfig V=1
配置过程如下所示:
在这里插入图片描述
可以看出,我们的分析是正确的,接下来就要结合下面两行命令重点分析一下文件 scripts/Makefile.build。
①、scripts_basic 目标对应的命令
@make -f ./scripts/Makefile.build obj=scripts/basic
②、%config 目标对应的命令
@make -f ./scripts/Makefile.build obj=scripts/kconfig xxx_defconfig

14、 Makefile.build 脚本分析
从上一小节可知,“make xxx_defconfig“配置 uboot 的时候如下两行命令会执行脚本scripts/Makefile.build:
@make -f ./scripts/Makefile.build obj=scripts/basic
@make -f ./scripts/Makefile.build obj=scripts/kconfig xxx_defconfig

依次来分析一下:
1、scripts_basic 目标对应的命令
scripts_basic 目标对应的命令为:@make -f ./scripts/Makefile.build obj=scripts/basic。打开文件 scripts/Makefile.build,有如下代码:
在这里插入图片描述
第 9 行定义了变量 prefix 值为 tpl。
第 10 行定义了变量 src,这里用到了函数 patsubst,此行代码展开后为:
$(patsubst tpl/%,%, scripts/basic)
patsubst 是替换函数,格式如下:
$(patsubst ,, )
此函数用于在 text 中查找符合 pattern 的部分,如果匹配的话就用 replacement 替换掉。pattenr 是可以包含通配符“%”,如果 replacement 中也包含通配符“%”,那么 replacement 中的这个“%”将是 pattern 中的那个“%”所代表的字符串。函数的返回值为替换后的字符串。因此,第 10 行就是在“scripts/basic”中查找符合“tpl/%”的部分,然后将“tpl/”取消掉,但是“scripts/basic”没有“tpl/”,所以 src= scripts/basic。
第 11 行判断变量 obj 和 src 是否相等,相等的话条件成立,很明显,此处条件成立。
第 12 行和第 9 行一样,只是这里处理的是“spl”,“scripts/basic”里面也没有“spl/”,所以src 继续为 scripts/basic。
第 15 行因为变量 obj 和 src 相等,所以 prefix=.。
继续分析 scripts/Makefile.build,有如下代码:
在这里插入图片描述
将 kbuild-dir 展开后为:
$(if $(filter /%, scripts/basic), scripts/basic, ./scripts/basic),
在这里插入图片描述
__build 是默认目标,因为命令“@make -f ./scripts/Makefile.build obj=scripts/basic”没有指定目标,所以会使用到默认目标:__build。在顶层 Makefile 中,KBUILD_BUILTIN 为 1,KBUILD_MODULES 为 0,因此展开后目标__build 为:
在这里插入图片描述
可以看出目标__build 有 5 个依赖:builtin-target、lib-target、extra-y、subdir-ym 和 always。这 5 个依赖的具体内容我们就不通过源码来分析了,直接在 scripts/Makefile.build 中输入图31.3.14.1 所示内容,将这 5 个变量的值打印出来:
在这里插入图片描述
执行如下命令:
make mx6ull_14x14_ddr512_emmc_defconfig V=1
结果如图所示:
在这里插入图片描述
从上图可以看出,只有 always 有效,因此__build 最终为:
__build: scripts/basic/fixdep
@:
__build 依赖于 scripts/basic/fixdep,所以要先编译 scripts/basic/fixdep.c,生成 fixdep,前面已经读取了 scripts/basic/Makefile 文件。
综上所述,scripts_basic 目标的作用就是编译出 scripts/basic/fixdep 这个软件。

2、%config 目标对应的命令
%config 目标对应的命令为: @make -f ./scripts/Makefile.build obj=scripts/kconfigxxx_defconfig,各个变量值如下:
src= scripts/kconfig
kbuild-dir = ./scripts/kconfig
kbuild-file = ./scripts/kconfig/Makefile
include ./scripts/kconfig/Makefile

可以看出,Makefilke.build 会读取 scripts/kconfig/Makefile 中的内容,此文件有如下所示内容:
在这里插入图片描述
目标%_defconfig 刚好和我们输入的 xxx_defconfig 匹配,所以会执行这条规则。依赖为$(obj)/conf,展开后就是 scripts/kconfig/conf。接下来就是检查并生成依赖 scripts/kconfig/conf。conf 是主机软件,到这里我们就打住,不要纠结 conf 是怎么编译出来的,否则就越陷越深,太绕了,像 conf 这种主机所使用的工具类软件我们一般不关心它是如何编译产生的。如果一定要看是 conf 是怎么生成的,可以输入如下命令重新配置 uboot,在重新配置 uboot 的过程中就会输出 conf 编译信息。
make distclean
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- mx6ull_14x14_ddr512_emmc_defconfig V=1

编译过程下图所示:
在这里插入图片描述
在这里插入图片描述
15、make过程
配置好 uboot 以后就可以直接 make 编译了,因为没有指明目标,所以会使用默认目标,主Makefile 中的默认目标如下:
在这里插入图片描述
在这里插入图片描述
如 果 KBUILD_EXTMOD 为 空 的 话 _all 依 赖 于 all 。 这 里 不 编 译 模 块 , 所 以KBUILD_EXTMOD 肯定为空,_all 的依赖就是 all。在主 Makefile 中 all 目标规则如下:
在这里插入图片描述
高级从 802 行可以看出,all 目标依赖(ALL-y),而在顶层 Makefile 中,ALL-y 如下:
在这里插入图片描述
在这里插入图片描述
从示例代码代码 31.3.15.3 可以看出,ALL-y 包含 u-boot.srec、u-boot.bin、u-boot.sym、System.map、u-boot.cfg 和 binary_size_check 这几个文件。根据 uboot 的配置情况也可能包含其他的文件,比如:
ALL-¥(CONFIG_ONENAND_U_BOOT) += u-boot-onenand.bin
CONFIG_ONENAND_U_BOOT 就是 uboot 中跟 ONENAND 配置有关的,如果我们使能了ONENAND,那么在.config 配置文件中就会有“CONFIG_ONENAND_U_BOOT=y”这一句。相当于 CONFIG_ONENAND_U_BOOT 是个变量,这个变量的值为“y”,所以展开以后就是:
ALL-y += u-boot-onenand.bin
这个就是.config 里面的配置参数的含义,这些参数其实都是变量,后面跟着变量值,会在顶层 Makefile 或者其他 Makefile 中调用这些变量。ALL-y 里面有个 u-boot.bin,这个就是我们最终需要的 uboot 二进制可执行文件,所作的所有工作就是为了它。在顶层 Makefile 中找到 u-boot.bin 目标对应的规则,如下所示
在这里插入图片描述
在这里插入图片描述
第 825 行判断 CONFIG_OF_SEPARATE 是否等于 y,如果相等,那条件就成立,在.config中搜索“CONFIG_OF_SEPARAT”,没有找到,说明条件不成立。
第 832 行就是目标 u-boot.bin 的规则,目标 u-boot.bin 依赖于 u-boot-nodtb.bin,命令为¥(call if_changed,copy) , 这 里 调 用 了if_changed , if_changed 是 一 个 函 数 , 这 个 函 数 在scripts/Kbuild.include 中有定义,而顶层 Makefile 中会包含 scripts/Kbuild.include 文件,这个前面已经说过了。if_changed 在 Kbuild.include 中的定义如下:
在这里插入图片描述
在这里插入图片描述
第 227 行为 if_changed 的描述,根据描述,在一些先决条件比目标新的时候,或者命令行有改变的时候,if_changed 就会执行一些命令。
第 257 行就是函数 if_changed,if_changed 函数引用的变量比较多,也比较绕,我们只需要知道它可以从 u-boot-nodtb.bin 生成 u-boot.bin 就行了。既然 u-boot.bin 依赖于 u-boot-nodtb.bin,那么肯定要先生成 u-boot-nodtb.bin 文件,顶层Makefile 中相关代码如下:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
图 31.3.15.2 就是“make”命令的执行流程,关于 uboot 的顶层 Makefile 就分析到这里,重点是“make xxx_defconfig”和“make”这两个命令的执行流程:
make xxx_defconfig:用于配置 uboot,这个命令最主要的目的就是生成.config 文件。
make:用于编译 uboot,这个命令的主要工作就是生成二进制的 u-boot.bin 文件和其他的一些与 uboot 有关的文件,比如 u-boot.imx 等等。
关于 uboot 的顶层 Makefile 就分析到这里,有些内容我们没有详细、深入的去研究,因为我们的重点是使用 uboot,而不是 uboot 的研究者,我们要做的是缕清 uboot 的流程。至于更具体的实现,有兴趣的可以参考一下其他资料。

  • 6
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值