其他分享
首页 > 其他分享> > U-Boot 之四 构建过程(Kconfig 配置 + Kbuild 编译)详解

U-Boot 之四 构建过程(Kconfig 配置 + Kbuild 编译)详解

作者:互联网

  在之前的博文 Linux 之八 完整嵌入式 Linux 环境介绍及搭建过程详解 中我们说了要一步步搭建整个嵌入式 Linux 运行环境,今天继续介绍 U-Boot 相关的内容。我所使用的硬件平台及整个要搭建的嵌入式 Linux 环境见博文 Linux 之八 完整嵌入式 Linux 环境介绍及搭建过程详解,没有特殊说明都是在以上环境中进行验证的,就不过多说明了。

  这篇博文我们仅仅关注 U-Boot 构建过程本身,想要吃透 U-Boot,有太多东西需要学习!最开始我想放到一篇文章中,写着写着内容越来越多,最终超过了 CSDN 编辑器的限制。。。最终决定把内容拆分成多篇文章。你可能需要:

  1. U-Boot 之一 零基础编译 U-Boot 过程详解 及 编译后的使用说明
  2. U-Boot 之二 详解使用 eclipse + J-Link 进行编译及在线调试
  3. U-Boot 之三 U-Boot 源码文件解析及移植过程详解
  4. U-Boot 之五 详解 U-Boot 及 SPL 的启动流程

Kbuild && Kconfig

  Kbuild && Kconfig 隶属于 Linux Kernel Build System。在宏观上,Kbuild && Kconfig 可以统称为 Kbuild,从微观上来说,Kbuild 指的是编译的过程,而 Kconfig 指的在编译之前对内核进行配置的过程(该过程中会编译一些工具来实现配置过程)。关于详细的可以查看 Linux Kernel 的官方文档 The Linux Kernel Documentation 中的 Kernel Build System 章节的介绍。

  1. 本文约定俗成的称呼:构建 指的 Kbuild + Kconfig;配置 指的 Kconfig;编译 指的 Kbuild。
  2. https://www.kernel.org/doc/

  Kbuild && Kconfig 这套构建系统一个显著的特点就是每一级目录都会有单独的相关文件,然后会被上一级相同的文件引用。这样就保证了每一级目录都是相互独立的。尤其是对于源码的维护者来说,这个是至关重要。每个维护者可以只关心他所负责的代码部分,任何更改只需要变更它自己的 Kbuild && Kconfig 相关文件即可。它本身主要包含以下几类文件:

  U-Boot 从 v2014.10 版本开始也引入 Kbuild && Kconfig 这套构建系统,相比于原来应该是复杂了不少。但是对于属性 Linux Kernel 的人来说确实是一个好消息!今天我们就来学习一下 U-Boot 中这套系统的具体工作流程。

  Kbuild && Kconfig 这套构建系统中定义了很多命令,我们可以使用 make help 来进行查看(就在根目录的 Makefile 文件中),其中经常用到命令如下图所示:
在这里插入图片描述

构建过程

  在 Kbuild && Kconfig 这套构建系统中,源码中使用的有些文件是要靠 Kbuild && Kconfig 这套系统来生成的,直接在源码中是找不到。这就要求我们必须要了解 Kbuild && Kconfig 是如何工作的,更重要的是要知道 Kbuild && Kconfig 会产生哪些源码使用的文件。

  整个构建过程的这个入口就是源码根目录下的 Makefile 文件。下面我们先来整体看一下这个文件的总体结构,并且对其中的规则进行一下说明。其大体可以分为三部分:
在这里插入图片描述
整个文件的前半部分就是定义一堆符号,检测工作环境、处理各种参数,基本没有实际与编译源码相关的命令。下面重点介绍一些(注意,由于我在其中添加了一些打印信息,导致行号与原文件有区别):

  至此,就开始根据给出的目标的不同开始区分具体操作类型了,后续我们单独章节来介绍!***注意,由于我在 Makefile 中添加了一些打印信息,导致行号与原文件有区别!***下面是我大体整理的一个流程图:
在这里插入图片描述

Kconfig

  在 Kbuild && Kconfig 这套构建系统中,当我们使用 make xxxconfg 类似的命令时,就会执行 Kconfig 流程。例如,当执行 make menuconfig 时会出现一个配置界面,允许开发者通过类似于 UI 的方式来对内核进行配置,之所为我们可以看到这个类似于 UI 的界面,就是因为 Kconfig 从中产生了多个文件和工具来实现的。

Kconfig 语法可以从 https://www.kernel.org/doc/html/latest/kbuild/kconfig-language.html 里来学习。

  当我们在 U-Boot 根目录执行 make menuconfig 或者 make xxx_deconfig 时,make 命令便会读取 U-Boot 根目录下的 Makefile 文件,然后解析并匹配 Makefile 文件中的规则 。而 xxxconfig 就会匹配根目录下 Makefile 文件中的如下图示的规则(% 可以匹配任意非空字符串,所以 menuconfig、xxx_deconfig 都匹配):
在这里插入图片描述

  经过上面的分析,最终由两条语句 make -f $(srctree)/scripts/Makefile.build obj=scripts/basicmake -f $(srctree)/scripts/Makefile.build obj=scripts/kconfig menuconfig 或者 make -f $(srctree)/scripts/Makefile.build obj=scripts/kconfig xxx_defconfig 是我们需要进一步来解析的。接下来就要进入 /scripts/Makefile.build 这个文件了。

Makefile.build

  对于 Makefile.build 文件,目前我们只需要关注下图所示的两部分(说明见注释):
在这里插入图片描述
接下就是进一步处理 scripts/basic/Makefile 或者 scripts/kconfig/Makefile 了。

make xxx_deconfig

  经过上面的分析,当我执行 make xxx_defconfig 时(例如,我这里的 make stm32f769-disco_defconfig),最终会执行以下两句:make -f $(srctree)/scripts/Makefile.build obj=scripts/basicmake -f $(srctree)/scripts/Makefile.build obj=scripts/kconfig xxx_defconfig
在这里插入图片描述

make menuconfig

  经过上面的分析,当我执行 make menuconfig 时,最终会执行以下两句:make -f $(srctree)/scripts/Makefile.build obj=scripts/basicmake -f $(srctree)/scripts/Makefile.build obj=scripts/kconfig menuconfig
在这里插入图片描述

  make xxx_deconfig之后,Kconfig 系统会在 U-Boot 源码根目录下生成 .config 文件,当我们使用 make menuconfig 修改了相关配置之后,Kconfig 系统最终也是修改根目录下的 .config 文件(注意,该文件默认是个隐藏文件,可使用 ls -al 查看),而 .config 文件就记录了我们当前对于 U-Boot 的配置,后续构建时便会读取该文件。

Kbuild

  这里说的 Kbuild 是微观上的 Kbuild,指的是编译的过程。在经过上面 Kconfig 之后,接下来就是真正的编译过程,这个过程采用的就是 Kbuild 系统。Linux 官方文档地址:https://www.kernel.org/doc/html/latest/kbuild/index.html。

  编译使用的命令是 CROSS_COMPILE=arm-none-eabi- ARCH=arm make -j8,当我们使用该命令之后,make 程序就会读取 U-Boot 根目录的 Makefile 文件,然后解析并匹配 Makefile 文件中的规则。由于这里没有指明目标,Make 会自动找到 makefile 中第一个目标中没有通配符的规则执行,这里就是 _all
在这里插入图片描述
  注意,这里的 _all 并不是第一个定义的 _all。第一个定义的 _all 是个空命令目标,空命令行可以防止 make 在执行时试图为重建这个目标去查找隐含命令(包括了使用隐含规则中的命令和“ .DEFAULT”指定的命令)。后面重新定义的 _all 才是最终生效的 _all

  如果 KBUILD_EXTMOD 为空的话 _all 依赖于 all。我们不编译模块(没有指定 KBUILD_EXTMOD),所以 KBUILD_EXTMOD 就是空 ,_all 依赖于 all 的。 all 又依赖 .binman_stmpinputs,如下图所示:
在这里插入图片描述
注意,如果使用的命令是 CROSS_COMPILE=arm-none-eabi- ARCH=arm make all -j8,则直接就会匹配到 all 这条规则,就不会有 _all 啥事了!

  .binman_stamp这个比较简单,就是通过使用 touch 命令更新 .binman_stamp 文件(不存在时会新建)的时间戳保证 binman 总是会被执行。然后检查一些定义,给出提示。
在这里插入图片描述
  重点就在 inputs,而 inputs 又是依赖于 $(INPUTS-y)。通过将 $(INPUTS-y) 展开后就是 checkarmreloc u-boot.srec u-boot.bin u-boot.sym System.map binary_size_check spl/u-boot-spl.bin u-boot.img u-boot.dtb u-boot-dtb.img 再进一步就是展开及处理各个依赖项了,下面我们重点来介绍一下 checkarmrelocu-boot.srec,其他的大家自行解析。

其实到这里基本就可以了,解析来就不继续深入了!下面来一张图:
在这里插入图片描述

clean、mrproper、distclean

  介绍了以上的工作过程之后,我们再介绍一下三个与清理相关的命令:cleanmrproperdistclean。至于支持的其他命令基本都差不多,大家感兴趣可以自己分析即可。这三个命令的清理程度是逐渐增加,后者包含前者,如下图所示:
在这里插入图片描述
我们就以 distclean 为例来说明。当我们执行 make distclean 这条命令时,make 读取根目录的 Makefile,然后开始解析,最终匹配到规则 distclean: mrproper,如下所示:
在这里插入图片描述

参考

  1. https://loee.xyz/2021/04/27/uboot-%E6%B5%81%E7%A8%8B%E5%88%86%E6%9E%90/
  2. https://www.cnblogs.com/humaoxiao/p/4189411.html
  3. https://github.com/zhaojh329/U-boot-1/blob/master/%E7%AC%AC9%E7%AB%A0-U-boot%E7%BC%96%E8%AF%91%E4%B9%8B%E4%B8%80%E9%85%8D%E7%BD%AE%E8%BF%87%E7%A8%8B.md
  4. https://blog.csdn.net/guyongqiangx/article/details/52558087
  5. https://yunyanan.github.io/exploring_kbuild/
  6. https://opensource.com/article/18/10/kbuild-and-kconfig
  7. https://www.cnblogs.com/syyxy/p/9350999.html
  8. https://blog.csdn.net/q_z_r_s/article/details/80783631
  9. https://blog.csdn.net/linuxweiyh/article/details/100528718

标签:Kconfig,kconfig,Makefile,make,Boot,Kbuild,scripts,built
来源: https://blog.csdn.net/ZCShouCSDN/article/details/122239526