【u-boot-2018.05】make配置过程分析
阅读原文时间:2023年07月15日阅读:1

https://blog.csdn.net/q_z_r_s/article/details/80718518

从u-boot-2014.10版本引入Kbuild系统之后,Makefile的管理和组织跟以前版本的代码有了很大的不同,这使Makefile变得更加复杂。整个Makefile中,include很多其它不同用途的Makefile,各种目标和依赖也很多,因此要想搞清楚make的执行过程很困难;使用u-boot之前首先是对其进行配置,命令为:

make xxx_defconfig

上述命令执行之后会生成对应的.config文件,接下来就可以进行最后的编译工作了,直接输入make即可。
配置流程分析

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

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

其中$(build)在kbuild.include中定义:

build := -f $(srctree)/scripts/Makefile.build obj

依赖scripts_basic:

# Basic helpers built in scripts/
    PHONY += scripts_basic
    scripts_basic:
        $(Q)$(MAKE) $(build)=scripts/basic
        $(Q)rm -f .tmp_quiet_recordmcount

可见scripts_basic没有进一步的依赖,展开后规则如下:

scripts_basic:
        $(Q) make -f ./scripts/Makefile.build obj=scripts/basic
        $(Q) rm -f .tmp_quiet_recordmcount

简而言之,scripts_basic规则

scripts_basic:
        $(Q) make -f ./scripts/Makefile.build obj=scripts/basic

的最终结果就是编译scripts/basic/fixdep.c生成主机上的可执行文件fixdep。

第二次调用scripts/Makefile.build进行编译
文件script/Makefile.build的开头会根据传入的obj=scripts/kconfig参数设置src=scripts/kconfig。然后搜寻$(srctree)/$(src)子目录下的makefile,由于src=scripts/kconfig参数不同于第一次调用的参数(src=scripts/basic),此处包含的makefile也不同于第一次的makefile了:

# The filename Kbuild has precedence over 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)

这里替换展开后相当于:

include ./scripts/kconfig/Makefile

对于这里传入的xxx_defconfig,匹配的目标是:

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

展开为:

xxx_defconfig: scripts/kconfig/conf
        $(Q)scripts/kconfig/conf  --defconfig=arch/../configs/xxx_defconfig Kconfig

此处目标xxx_defconfig依赖于scripts/kconfig/conf,接下来检查并生成依赖。

hostprogs-y := conf nconf mconf kxgettext qconf gconf

hostprogs-y指出conf被定义为主机上执行的程序,其依赖于另外两个文件:

conf-objs   := conf.o  zconf.tab.o

通过编译conf.c和zconf.tab.c生成conf-objs,并链接为scripts/kconfig/conf。

生成依赖后就是执行目标的命令了:

$(Q)scripts/kconfig/conf  --defconfig=arch/../configs/xxx_defconfig Kconfig

conf工具从根目录下开始树状读取默认的Kconfig文件,分析其配置并保存在内存中。分析完默认的Kconfig后再读取指定文件(即arch/../configs/xxx_defconfig)更新得到最终的符号表,并输出到.config文件中。

u-boot-2016 make配置过程分析

本文基于u-boot树莓派3代配置过程进行分析,环境如下:
编译环境:Ubuntu 14.04 LTS
编译工具:arm-[Linux](http://lib.csdn.net/base/linux)-gnueabi-gcc

代码版本:u-boot v2016.09
配置文件:rpi_3_32b_defconfig

u-boot自v2014.10版本开始引入KBuild系统,Makefile的管理和组织跟以前版本的代码有了很大的不同,其Makefile更加复杂。整个Makefile中,嵌套了很多其它不同用途的Makefile,各种目标和依赖也很多,make分析很容易陷进去,让人摸不着头脑。

本文涉及的配置命令:

make rpi_3_32b_defconfig

u-boot的编译跟kernel编译一样,分两步执行:
- 第一步:配置,执行make xxx_defconfig进行各项配置,生成.config文件
- 第二部:编译,执行make进行编译,生成可执行的二进制文件u-boot.bin或u-boot.elf

先从简单的make defconfig配置过程着手吧。
命令行输入:

make rpi_3_32b_defconfig V=1

编译输出如下:

配置命令参数说明:
- rpi_3_32b_defconfig 是树莓派3代32位编译的配置文件
- V=1 指示编译显示详细的输出。默认V=0,编译仅显示必要的简略信息

从输出的log看,make rpi_3_32b_defconfig的执行主要分为3个部分,见图上的标示:
- 1. 执行make -f ./scripts/Makefile.build obj=scripts/basic,编译生成scripts/basic/fixdep工具

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

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

跟原始的代码相比,执行make rpi_3_32b_defconfig后文件夹内容的变化如下:

被后续编译用到的文件是.config。

言归正传,整个配置流程的目的就是为了生成.config文件,下面详细分析.config文件是如何一步一步生成的。

Makefile的核心是依赖和命令。对于每个目标,首先会检查依赖,如果依赖存在,则执行命令更新目标;如果依赖不存在,则会以依赖为目标,先生成依赖,待依赖生成后,再执行命令生成目标。

1. 顶层make defconfig规则

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

  1. %config: scripts_basic outputmakefile FORCE

  2. $(Q)$(MAKE) $(build)=scripts/kconfig $@

对于目标,rpi_3_32b_defconfig,展开则有:

手机扫一扫

移动阅读更方便

阿里云服务器
腾讯云服务器
七牛云服务器