UBOOT编译--- UBOOT全部目标的编译过程详解(九)
阅读原文时间:2023年07月09日阅读:3

1. 前言

 UBOOT版本:uboot2018.03,开发板myimx8mmek240。

2. 概述

本文接续上篇文章,采用自下而上的方法,先从最原始的依赖开始,一步一步,执行命令生成目标。这里先把上节所有依赖关系再次列在这里:

                                                                                              --------------------------------------------|
                                                                                             | arch/arm/cpu  \             $(u-boot-dirs)|
                                                         arch/arm/cpu/built-in.o \           | arch/arm/cpu/armv8 \            的值      |
                                                         arch/arm/cpu/armv8/built-in.o \     | arch/arm/lib \                            |
                                                         arch/arm/lib/built-in.o \           | arch/arm/mach-imx \                       |
                                                         arch/arm/mach-imx/built-in.o \      | board/myzr/common  \                      |
                                                         board/myzr/common/built-in.o  \     | board/myzr/myimx8mm  \                    |
                                                         board/myzr/myimx8mm/built-in.o  \   | cmd  \                                    |
                                                         cmd/built-in.o  \                   | common  \                                 |
                                                         common/built-in.o  \                | disk  \                                   |
                                                         disk/built-in.o  \                  | drivers \                                 |
                                                         drivers/built-in.o  \               | drivers/dma  \                            |
                                                         drivers/dma/built-in.o  \           | drivers/gpio  \                           |
                                                         drivers/gpio/built-in.o  \          | drivers/i2c  \                            |
include/config/auto.conf scripts_basic                   drivers/i2c/built-in.o  \           | drivers/mtd \                             |
            \            /                               drivers/mtd/built-in.o  \           | drivers/mtd/onenand  \                    |
             \          /                                drivers/mtd/onenand/built-in.o  \   | drivers/mtd/spi \                         |
              \        /                                 drivers/mtd/spi/built-in.o  \       | drivers/net  \                            |
                scripts                    prepare       drivers/net/built-in.o  \           | drivers/net/phy  \                        |
                -----                     -----          drivers/net/phy/built-in.o  \       |      .                                    |
                  \                      /                    .                              |      .                                    |
                   \                    /                     .                              |      .                                    |
                    \                  /                      .                              | env  \                                    |
                     \                /                  env/built-in.o  \                   | fs  \                                     |
                        $(u-boot-dirs)                   fs/built-in.o  \                    | lib  \                                    |
                 -------------------------               lib/built-in.o  \                   | net  \                                    |
                 |                        \              net/built-in.o  \                   | test \                                    |
                 |                         \             test/built-in.o  \                  | test/dm                                   |
                 |          依赖            \            test/dm/built-in.o                  ---------------------------------------------
                 |                           \              ||                                                            include/config/uboot.release
                 |                            \             ||         arch/arm/cpu/armv8/u-boot.lds                           |
                 |                             \            ||              ||                       outputmakefile          prepare3
         $(u-boot-init)==$(head-y)             $(u-boot-main)==        u-boot.lds      FORCE                 \                 /
         arch/arm/cpu/armv8/start.o                 $(libs-y)            /             /                      \               /
                                \                     |                 /             /                        \             /
                                 \                    |                /             /                          \           /
                                  \                   |               /             /                            \         /      include/generated/version_autogenerated.h    include/generated/timestamp_autogenerated.h
                                   \                  |              /             /                              \       /           |                           /
                                    \                 |             /             /                                \     /            |                          /
                                    ----------------------------------------------                                 prepare2        $(version_h)          $(timestamp_h)   include/config/auto.conf(auto.conf里去掉了.config中的注释项目以及空格行,其它的都一样)
                                                      |                                                                 \             \                   /                /
                                                      |                                                                  \             \                 /                /
                                                    u-boot                                                                \             \               /                /
                       ---------------------------------------------------------------------------------------             \             \             /                /
                       /                          /                                      \         \          \             -------------------------------------------
                      /                          /                                        \         \          \                    prepare1                                   scripts_basic
                     /                           |                                         \         \          \                   -------                                    -------------
                    |                            |                                          |         |         |                     \                                           /
                    |                        dts/dt.dtb                                     |         |         |                      \                                         /
                    |               --------------------------                              |         |         |                       -----------------------------------------
                    |              /                   /     |                              |         |         |                              archprepare
              u-boot-nodtb.bin    /                   /      |                              |         |         |                              ----------
              ---------------    /                   /       |                              |         |         |                                  |
                    |  \     \  /                   /        |                              |         |         |                                  |
                    |   \     \/                   /         |                              |         |         |                               prepare0
                    |    \    /\                  /          |                              |         |         |                               --------
                    |     \  /  \                /           |                              |         |         |                                  |
                    |      \/    \-------\      /            |                              |         |         |                                  |
                    |      /\             \    /             |                              |         |         |            tools             prepare
                    |     /  \             \  /              |                              |         |         |            -----             -----
                    |    /    \             \/               |                              |         |         |              \                 /
               u-boot-dtb.bin  \            /\               |                              |         |         |               \               /
               --------------   \          /  \-----------\  |                              |         |         |                \             /
                    |            \        /                \ |                              |         |         |                 \           /
                    |             \      /                  \|                              |         |         |                spl/u-boot-spl
                    |              \    /                    \                              |         |         |                --------------
                    |               \  /                     |\--------------|              |         |         |                     |
                    |                \/                      |               |              |         |         |                     |
              u-boot.bin    u-boot.img/u-boot-dtb.img     u-boot.dtb    binary_size_check  u-boot.srec u-boot.sym System.map   spl/u-boot-spl.bin
              ----------   --------------------------      ---------    -----------------  ----------- ---------   --------    -----------------
             /         |                  |                    |               |               |         |            |                |
            /          |                  |                    |               |               |         |            |                |
           /           |                  |                    |               |               |         |            |                |
 u-boot.elf            |                  |                    |               |               |         |            |                |
  ---------            |                  |                    |               |               |         |            |                |
           \           |                  |                    |               |               |         |            |                |
            \          |                  |                    |               |               |         |            |                |
             \         \                  \                    |               /               /         /            /               /                             include/config.h
              \         \                  \                   |              /               /         /            /               /                                    |
               \         \                  \                  |             /               /         /            /               /                                     |
                \         \                  \                 |            /               /         /            /               /                                      |
                 \         \                  \                |           /               /         /            /               /                                       |
                  \         \                  \               |          /               /         /            /               /                                    u-boot.cfg
                   \         \                  \              |         /               /         /            /               /                                          |
                    \         \                  \             |        /               /         /            /               /                                           |
                     ----------------------------------------------------------------------------------------------------------                                            |
                                                            $(ALL-y)                                                                                                      cfg
                                                                \                                                                                                         /
                                                                 \                                                                                                       /
                                                                  \                                                                                                     /
                                                                   -----------------------------------------------------------------------------------------------------
                                                                                                                      all
                                                                                                                       |
                                                                                                                     _all

3. 构建include/config/auto.conf

参见:UBOOT编译--- include/config/auto.conf、 include/config/auto.conf.cmd、 include/generated/autoconf.h (二)。auto.conf 和 .config 的差别是:auto.conf 里去掉了 .config 中的注释项目以及空格行,其它的都一样。

4. 构建scripts_basic 、scripts

参见:UBOOT编译--- make xxx_deconfig过程详解(一) - 4.1 依赖 scripts_basic

<<<<<<<<<顶层Makefile>>>>>>>>>
# ===========================================================================
# Build targets only - this includes vmlinux, arch specific targets, clean
# targets and others. In general all targets except *config targets.

# Additional helpers built in scripts/
# Carefully list dependencies so we do not try to build scripts twice
# in parallel
PHONY += scripts
scripts: scripts_basic include/config/auto.conf
    $(Q)$(MAKE) $(build)=$(@)         //规则

规则展开后为:make -f $(srctree)/scripts/Makefile.build obj=scripts。未指定目标,采用Makefile.build中的默认目标__build。且在Makefile.build中会引用scripts目录下的Makefile

4.2.1 make -f $(srctree)/scripts/Makefile.build obj=scripts分析

# <<<<<<<<<scripts/Makefile.build>>>>>>>>>
PHONY := __build
__build:

# The filename Kbuild has precedence over Makefile
kbuild-dir := $(if $(filter /%,$(src)),$(src),$(srctree)/$(src))   //   scripts/
kbuild-file := $(if $(wildcard $(kbuild-dir)/Kbuild),$(kbuild-dir)/Kbuild,$(kbuild-dir)/Makefile) //   scripts/Makefile
include $(kbuild-file)                                   (1)//include scripts/Makefile 

......

include scripts/Makefile.lib   //要关注这个引用位置 在include $(kbuild-file)之后.下面第6项会用来解析subdir-ym

......

ifneq ($(strip $(lib-y) $(lib-m) $(lib-)),)
lib-target := $(obj)/lib.a                              (2)lib-target :=
endif

ifneq ($(strip $(obj-y) $(obj-m) $(obj-) $(subdir-m) $(lib-target)),)//去空格函数—strip
builtin-target := $(obj)/built-in.o                      (3) builtin-target :=
endif

modorder-target := $(obj)/modules.order

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

# Descending
# ---------------------------------------------------------------------------
PHONY += $(subdir-ym)
$(subdir-ym):
    $(Q)$(MAKE) $(build)=$@

1. 引用scripts/Makefile

# <<<<<<<<<scripts/Makefile>>>>>>>>>
hostprogs-$(CONFIG_BUILD_BIN2C)        += bin2c //CONFIG_BUILD_BIN2C未定义

always        := $(hostprogs-y) //特别注意always定义的这个位置
//由于 Makefile中
//(1)使用“=”进行赋值,变量的值是整个makefile中最后被指定的值;
//(2)使用":="进行赋值,即根据当前位置进行赋值
// 因此这里的always只与hostprogs-$(CONFIG_BUILD_BIN2C)的定义有关,与后面的hostprogs-y无关
# The following hostprogs-y programs are only build on demand
hostprogs-y += docproc        

# These targets are used internally to avoid "is up to date" messages
PHONY += build_docproc
build_docproc: $(obj)/docproc
    @:

# Let clean descend into subdirs
subdir-    += basic kconfig
subdir-$(CONFIG_DTC)    += dtc //有定义

特别注意always定义的这个位置,由于CONFIG_BUILD_BIN2C未定义,always为空(注意always后面的hostprogs-y不生效)。此外CONFIG_DTC定义为y,因此subdir-y+= dtc。

2. lib-target的定义

ifneq ($(strip $(lib-y) $(lib-m) $(lib-)),)
lib-target := $(obj)/lib.a                              (2)lib-target :=
endif

$(lib-y) $(lib-m) $(lib-)在scripts/Makefile中均未定义,因此lib-target := 。

3. builtin-target的定义

ifneq ($(strip $(obj-y) $(obj-m) $(obj-) $(subdir-m) $(lib-target)),)//去空格函数—strip
builtin-target := $(obj)/built-in.o                      (3) builtin-target :=
endif

$(obj-y) $(obj-m) $(obj-) $(subdir-m) $(lib-target)在scripts/Makefile中均未定义,因此builtin-target:= 。

4. extra-y的定义

extra-y 在scripts/Makefile中未定义,因此extra-y:= 。

5. always的定义

在scripts/Makefile中always为空,因此always:= 。

6. subdir-ym的定义

# <<<<<<<<<scripts/Makefile.lib >>>>>>>>>
# Subdirectories we need to descend into

subdir-ym    := $(sort $(subdir-y) $(subdir-m))  // dtc

......

subdir-ym    := $(addprefix $(obj)/,$(subdir-ym))  //scripts/dtc

subdir-ym定义在在scripts/Makefile.lib中,展开为scripts/dtc 。要想构建默认目标__build,要先构建依赖$ (subdir-ym)(即scripts/dtc)。$(subdir-ym)的规则也定义在Makefile.build中(递归调用),就是执行make -f ./scripts/Makefile.build obj=scripts/dtc

4.2.1.1 make -f ./scripts/Makefile.build obj=scripts/dtc分析

make -f ./scripts/Makefile.build obj=scripts/dtc由于未指定目标,采用Makefile.build中的默认目标__build

# <<<<<<<<<scripts/Makefile.build>>>>>>>>>
PHONY := __build
__build:

# 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/dtc/Makefile                         (1)

......

include scripts/Makefile.lib   //要关注这个引用位置 在include $(kbuild-file)之后 (2)

......

# Do not include host rules unless needed
ifneq ($(hostprogs-y)$(hostprogs-m),)
include scripts/Makefile.host //要关注这个引用                                  (3)
endif

......

ifneq ($(strip $(lib-y) $(lib-m) $(lib-)),)
lib-target := $(obj)/lib.a                              (4)lib-target :=
endif

ifneq ($(strip $(obj-y) $(obj-m) $(obj-) $(subdir-m) $(lib-target)),)//去空格函数—strip
builtin-target := $(obj)/built-in.o                      (5) builtin-target :=
endif

modorder-target := $(obj)/modules.order
......

__build: $(if $(KBUILD_BUILTIN),$(builtin-target) $(lib-target) $(extra-y)) \
     $(if $(KBUILD_MODULES),$(obj-m) $(modorder-target)) \
     $(subdir-ym) $(always)
    @:

1. 引用scripts/dtc目录下的Makefile

# <<<<<<<<<scripts/dtc/Makefile>>>>>>>>>

hostprogs-y    := dtc
always        := $(hostprogs-y)    //always := dtc

dtc-objs    := dtc.o flattree.o fstree.o data.o livetree.o treesource.o \
           srcpos.o checks.o util.o
dtc-objs    += dtc-lexer.lex.o dtc-parser.tab.o

# Source files need to get at the userspace version of libfdt_env.h to compile

HOSTCFLAGS_DTC := -I$(src) -I$(src)/libfdt

HOSTCFLAGS_checks.o := $(HOSTCFLAGS_DTC)
HOSTCFLAGS_data.o := $(HOSTCFLAGS_DTC)
HOSTCFLAGS_dtc.o := $(HOSTCFLAGS_DTC)
HOSTCFLAGS_flattree.o := $(HOSTCFLAGS_DTC)
HOSTCFLAGS_fstree.o := $(HOSTCFLAGS_DTC)
HOSTCFLAGS_livetree.o := $(HOSTCFLAGS_DTC)
HOSTCFLAGS_srcpos.o := $(HOSTCFLAGS_DTC)
HOSTCFLAGS_treesource.o := $(HOSTCFLAGS_DTC)
HOSTCFLAGS_util.o := $(HOSTCFLAGS_DTC)

HOSTCFLAGS_dtc-lexer.lex.o := $(HOSTCFLAGS_DTC)
HOSTCFLAGS_dtc-parser.tab.o := $(HOSTCFLAGS_DTC)

# dependencies on generated files need to be listed explicitly
$(obj)/dtc-lexer.lex.o: $(obj)/dtc-parser.tab.h

# generated files need to be cleaned explicitly
clean-files    := dtc-lexer.lex.c dtc-parser.tab.c dtc-parser.tab.h

# Added for U-Boot
subdir-$(CONFIG_PYLIBFDT) += pylibfdt //未定义CONFIG_PYLIBFDT

2. 引用scripts/Makefile.lib

# <<<<<<<<<scripts/Makefile.lib>>>>>>>>>
always        := $(addprefix $(obj)/,$(always))  //always := scripts/dtc/dtc

3. 引用scripts/Makefile.host

# <<<<<<<<<scripts/Makefile.host>>>>>>>>>
__hostprogs := $(sort $(hostprogs-y) $(hostprogs-m))            //(1) = dtc

# C executables linked based on several .o files
host-cmulti    := $(foreach m,$(__hostprogs),\
           $(if $($(m)-cxxobjs),,$(if $($(m)-objs),$(m))))      //(2) dtc

# Object (.o) files compiled from .c files
host-cobjs    := $(sort $(foreach m,$(__hostprogs),$($(m)-objs)))//(3) dtc-objs

......

__hostprogs     := $(addprefix $(obj)/,$(__hostprogs))         //(4) scripts/dtc/dtc-objs
host-cmulti    := $(addprefix $(obj)/,$(host-cmulti))             //(5) scripts/dtc/dtc
host-cobjs    := $(addprefix $(obj)/,$(host-cobjs))              //(6) cripts/dtc/**.o

......

# Link an executable based on list of .o files, all plain c
# host-cmulti -> executable
quiet_cmd_host-cmulti    = HOSTLD  $@
      cmd_host-cmulti    = $(HOSTCC) $(HOSTLDFLAGS) -o $@ \
              $(addprefix $(obj)/,$($(@F)-objs)) \
              $(HOST_LOADLIBES) $(HOSTLOADLIBES_$(@F))        //(7) scripts/dtc/dtc的编译 == $(always)
$(host-cmulti): FORCE
    $(call if_changed,host-cmulti)
$(call multi_depend, $(host-cmulti), , -objs)

# Create .o file from a single .c file
# host-cobjs -> .o
quiet_cmd_host-cobjs    = HOSTCC  $@
      cmd_host-cobjs    = $(HOSTCC) $(hostc_flags) -c -o $@ $<  //(6) 所有.o的编译
$(host-cobjs): $(obj)/%.o: $(src)/%.c FORCE
    $(call if_changed_dep,host-cobjs)

4. lib-target的定义

ifneq ($(strip $(lib-y) $(lib-m) $(lib-)),)
lib-target := $(obj)/lib.a                              (2)lib-target :=
endif

$(lib-y) $(lib-m) $(lib-)在scripts/Makefile中均未定义,因此lib-target := 。

5. builtin-target的定义

ifneq ($(strip $(obj-y) $(obj-m) $(obj-) $(subdir-m) $(lib-target)),)//去空格函数—strip
builtin-target := $(obj)/built-in.o                      (3) builtin-target :=
endif

$(obj-y) $(obj-m) $(obj-) $(subdir-m) $(lib-target)在scripts/Makefile中均未定义,因此builtin-target:= 。

6. extra-y的定义

extra-y 在scripts/Makefile中未定义,因此extra-y:= 。

7. always的定义

在scripts/dtc/Makefil中定义为dtc,在scripts/Makefile.lib中添加目录前缀,最终为scripts/dtc/dtc。

8. subdir-ym的定义

subdir-ym为空。

综上,对于make -f ./scripts/Makefile.build obj=scripts/dtc:

  • KBUILD_BUILTIN为y,$(builtin-target) $(lib-target) $(extra-y)为空;
  • $(subdir-ym)为空;
  • $(always)为scripts/dtc/dtc;
  • 展开为:
  • __build: $(always)
  •     @:

要想构建默认目标__build,要先构建依赖$ (always)(即scripts/dtc/dtc)。构建$ (always)等价于构建$(host-cmulti)

编译打印命令如下:

make -f ./scripts/Makefile.build obj=scripts
  HOSTCC  scripts/dtc/dtc.o
  HOSTCC  scripts/dtc/flattree.o
  HOSTCC  scripts/dtc/fstree.o
  HOSTCC  scripts/dtc/data.o
  HOSTCC  scripts/dtc/livetree.o
  HOSTCC  scripts/dtc/treesource.o
  HOSTCC  scripts/dtc/srcpos.o
  HOSTCC  scripts/dtc/checks.o
  HOSTCC  scripts/dtc/util.o
  SHIPPED scripts/dtc/dtc-lexer.lex.c
  SHIPPED scripts/dtc/dtc-parser.tab.h
  HOSTCC  scripts/dtc/dtc-lexer.lex.o
  SHIPPED scripts/dtc/dtc-parser.tab.c
  HOSTCC  scripts/dtc/dtc-parser.tab.o
  HOSTLD  scripts/dtc/dtc

真实执行的完整命令如下:

make -f ./scripts/Makefile.build obj=scripts
make -f ./scripts/Makefile.build obj=scripts/dtc
  cc -Wp,-MD,scripts/dtc/.dtc.o.d -Wall -Wstrict-prototypes -O2 -fomit-frame-pointer     -Iscripts/dtc -Iscripts/dtc/libfdt -c -o scripts/dtc/dtc.o scripts/dtc/dtc.c
  cc -Wp,-MD,scripts/dtc/.flattree.o.d -Wall -Wstrict-prototypes -O2 -fomit-frame-pointer     -Iscripts/dtc -Iscripts/dtc/libfdt -c -o scripts/dtc/flattree.o scripts/dtc/flattree.c
  cc -Wp,-MD,scripts/dtc/.fstree.o.d -Wall -Wstrict-prototypes -O2 -fomit-frame-pointer     -Iscripts/dtc -Iscripts/dtc/libfdt -c -o scripts/dtc/fstree.o scripts/dtc/fstree.c
  cc -Wp,-MD,scripts/dtc/.data.o.d -Wall -Wstrict-prototypes -O2 -fomit-frame-pointer     -Iscripts/dtc -Iscripts/dtc/libfdt -c -o scripts/dtc/data.o scripts/dtc/data.c
  cc -Wp,-MD,scripts/dtc/.livetree.o.d -Wall -Wstrict-prototypes -O2 -fomit-frame-pointer     -Iscripts/dtc -Iscripts/dtc/libfdt -c -o scripts/dtc/livetree.o scripts/dtc/livetree.c
  cc -Wp,-MD,scripts/dtc/.treesource.o.d -Wall -Wstrict-prototypes -O2 -fomit-frame-pointer     -Iscripts/dtc -Iscripts/dtc/libfdt -c -o scripts/dtc/treesource.o scripts/dtc/treesource.c
  cc -Wp,-MD,scripts/dtc/.srcpos.o.d -Wall -Wstrict-prototypes -O2 -fomit-frame-pointer     -Iscripts/dtc -Iscripts/dtc/libfdt -c -o scripts/dtc/srcpos.o scripts/dtc/srcpos.c
  cc -Wp,-MD,scripts/dtc/.checks.o.d -Wall -Wstrict-prototypes -O2 -fomit-frame-pointer     -Iscripts/dtc -Iscripts/dtc/libfdt -c -o scripts/dtc/checks.o scripts/dtc/checks.c
  cc -Wp,-MD,scripts/dtc/.util.o.d -Wall -Wstrict-prototypes -O2 -fomit-frame-pointer     -Iscripts/dtc -Iscripts/dtc/libfdt -c -o scripts/dtc/util.o scripts/dtc/util.c
  cat scripts/dtc/dtc-lexer.lex.c_shipped > scripts/dtc/dtc-lexer.lex.c
  cat scripts/dtc/dtc-parser.tab.h_shipped > scripts/dtc/dtc-parser.tab.h
  cc -Wp,-MD,scripts/dtc/.dtc-lexer.lex.o.d -Wall -Wstrict-prototypes -O2 -fomit-frame-pointer     -Iscripts/dtc -Iscripts/dtc/libfdt -c -o scripts/dtc/dtc-lexer.lex.o scripts/dtc/dtc-lexer.lex.c
  cat scripts/dtc/dtc-parser.tab.c_shipped > scripts/dtc/dtc-parser.tab.c
  cc -Wp,-MD,scripts/dtc/.dtc-parser.tab.o.d -Wall -Wstrict-prototypes -O2 -fomit-frame-pointer     -Iscripts/dtc -Iscripts/dtc/libfdt -c -o scripts/dtc/dtc-parser.tab.o scripts/dtc/dtc-parser.tab.c
  cc  -o scripts/dtc/dtc scripts/dtc/dtc.o scripts/dtc/flattree.o scripts/dtc/fstree.o scripts/dtc/data.o scripts/dtc/livetree.o scripts/dtc/treesource.o scripts/dtc/srcpos.o scripts/dtc/checks.o scripts/dtc/util.o scripts/dtc/dtc-lexer.lex.o scripts/dtc/dtc-parser.tab.o

综上,对于make -f $(srctree)/scripts/Makefile.build obj=scripts,默认目标__build:

  • KBUILD_BUILTIN为y,$(builtin-target) $(lib-target) $(extra-y)为空 ;
  • $(subdir-ym)为scripts/dtc;
  • $(always)为空;
  • 展开为:
  • __build: scripts/dtc
  •     @:

5. 构建prepare、prepare0、prepare1、prepare2、prepare3、archprepare

# Things we need to do before we recursively start building the kernel
# or the modules are listed in "prepare".
# A multi level approach is used. prepareN is processed before prepareN-1.
# archprepare is used in arch Makefiles and when processed asm symlink,
# version.h and scripts_basic is processed / created.

# Listed in dependency order
PHONY += prepare archprepare prepare0 prepare1 prepare2 prepare3

# prepare3 is used to check if we are building in a separate output directory,
# and if so do:
# 1) Check that make has not been executed in the kernel src $(srctree)
prepare3: include/config/uboot.release
ifneq ($(KBUILD_SRC),)
    @$(kecho) '  Using $(srctree) as source for U-Boot'
    $(Q)if [ -f $(srctree)/.config -o -d $(srctree)/include/config ]; then \
        echo >&2 "  $(srctree) is not clean, please run 'make mrproper'"; \
        echo >&2 "  in the '$(srctree)' directory.";\
        /bin/false; \
    fi;
endif

# prepare2 creates a makefile if using a separate output directory
prepare2: prepare3 outputmakefile

prepare1: prepare2 $(version_h) $(timestamp_h) \
                   include/config/auto.conf
ifeq ($(wildcard $(LDSCRIPT)),)
    @echo >&2 "  Could not find linker script."
    @/bin/false
endif

archprepare: prepare1 scripts_basic

prepare0: archprepare FORCE
    $(Q)$(MAKE) $(build)=.  //规则

# All the preparing..
prepare: prepare0

伪目标prepare依赖prepare0;prepare0又依赖 archprepare、FORCE;archprepare又依赖prepare1和scripts_basic;prepare1又依赖于

repare2、$ (version_h) 、$ (timestamp_h) 、 include/config/auto.conf;prepare2又依赖prepare3和outputmakefile;prepare3又依赖include/config/uboot.release,如果KBUILD_SRC为空,没有规则。涉及的具体目标链接:

除了prepare0有具体规则外,其它都是伪目标。

规则为:

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

在Makefile.build会引用当前目录下的Kbuild(注意这个引用的不是Makefile):

# <<<<<<<<<scripts/Makefile.build>>>>>>>>>
# 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)//    ././Kbuild
include $(kbuild-file)                                   (1)//include ././Kbuild
......

ifneq ($(strip $(lib-y) $(lib-m) $(lib-)),)
lib-target := $(obj)/lib.a                              (2)lib-target :=
endif

ifneq ($(strip $(obj-y) $(obj-m) $(obj-) $(subdir-m) $(lib-target)),)//去空格函数—strip
builtin-target := $(obj)/built-in.o                      (3) builtin-target :=
endif

modorder-target := $(obj)/modules.order

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

1. 引用顶层目录Kbuild

# <<<<<<<<<Kbuild>>>>>>>>>
# 1) Generate generic-asm-offsets.h

generic-offsets-file := include/generated/generic-asm-offsets.h

always  := $(generic-offsets-file)  //include/generated/generic-asm-offsets.h
targets := lib/asm-offsets.s

# We use internal kbuild rules to avoid the "is up to date" message from make
lib/asm-offsets.s: lib/asm-offsets.c FORCE
    $(Q)mkdir -p $(dir $@)
    $(call if_changed_dep,cc_s_c)

$(obj)/$(generic-offsets-file): lib/asm-offsets.s FORCE
    $(call filechk,offsets,__GENERIC_ASM_OFFSETS_H__)

#####
# 2) Generate asm-offsets.h
#

ifneq ($(wildcard $(srctree)/arch/$(ARCH)/lib/asm-offsets.c),)//成立
offsets-file := include/generated/asm-offsets.h
endif

always  += $(offsets-file) //include/generated/asm-offsets.h
targets += arch/$(ARCH)/lib/asm-offsets.s

CFLAGS_asm-offsets.o := -DDO_DEPS_ONLY

# We use internal kbuild rules to avoid the "is up to date" message from make
arch/$(ARCH)/lib/asm-offsets.s: arch/$(ARCH)/lib/asm-offsets.c FORCE
    $(Q)mkdir -p $(dir $@)
    $(call if_changed_dep,cc_s_c)

$(obj)/$(offsets-file): arch/$(ARCH)/lib/asm-offsets.s FORCE
    $(call filechk,offsets,__ASM_OFFSETS_H__)

2. lib-target的定义

ifneq ($(strip $(lib-y) $(lib-m) $(lib-)),)
lib-target := $(obj)/lib.a                              (2)lib-target :=
endif

$(lib-y) $(lib-m) $(lib-)在顶层目录Kbuild中均未定义,因此lib-target := 。

3. builtin-target的定义

ifneq ($(strip $(obj-y) $(obj-m) $(obj-) $(subdir-m) $(lib-target)),)//去空格函数—strip
builtin-target := $(obj)/built-in.o                      (3) builtin-target :=
endif

$(obj-y) $(obj-m) $(obj-) $(subdir-m) $(lib-target)在顶层目录Kbuild中均未定义,因此builtin-target:= 。

4. always的定义

在kbuild中定义为include/generated/asm-offsets.h和include/generated/asm-offsets.h 。

综上,对于默认目标__build:

  • KBUILD_BUILTIN为y,$(builtin-target) $(lib-target) $(extra-y)为空 ;
  • $(subdir-ym)为空(注意并不是所有的编译目标都是空);
  • $(always)为nclude/generated/asm-offsets.h、include/generated/asm-offsets.h;
  • 展开为:
  • __build: include/generated/asm-offsets.h include/generated/asm-offsets.h
  •     @:

include/generated/asm-offsets.h 、include/generated/asm-offsets.h 的规则定义在顶层目录Kbuild中,如本小节(1)。

5.1.1 include/generated/generic-asm-offsets.h的编译(通用)

# <<<<<<<<<scripts/Kbuild.include:>>>>>>>>>
###
# filechk is used to check if the content of a generated file is updated.
# Sample usage:
# define filechk_sample
#    echo $KERNELRELEASE
# endef
# version.h : Makefile
#    $(call filechk,sample)
# The rule defined shall write to stdout the content of the new file.
# The existing file will be compared with the new one.
# - If no file exist it is created
# - If the content differ the new file is used
# - If they are equal no change, and no timestamp update
# - stdin is piped in from the first prerequisite ($<) so one has
#   to specify a valid file as first prerequisite (often the kbuild file)
define filechk
    $(Q)set -e;                \
    $(kecho) '  CHK     $@';      \      //打印'  CHK     include/generated/generic-asm-offsets.h'
    mkdir -p $(dir $@);           \          //创建  include/generated/目录
    $(filechk_$(1)) < $< > $@.tmp;      \  //调用filechk_offsets < lib/asm-offsets.s > include/generated/generic-asm-offsets.h.tmp
    if [ -r $@ ] && cmp -s $@ $@.tmp; then   \  //如果存在目标,则比较更新,否则把$@.tmp更名为$@
        rm -f $@.tmp;          \
    else                    \
        $(kecho) '  UPD     $@';  \
        mv -f $@.tmp $@;      \
    fi
endef

# <<<<<<<<<Kbuild>>>>>>>>>
#
# Kbuild for top-level directory of U-Boot
# This file takes care of the following:
# 1) Generate generic-asm-offsets.h
# 2) Generate asm-offsets.h

# Default sed regexp - multiline due to syntax constraints
define sed-y
    "s:[[:space:]]*\.ascii[[:space:]]*\"\(.*\)\":\1:; \
    /^->/{s:->#\(.*\):/* \1 */:; \
    s:^->\([^ ]*\) [\$$#]*\([-0-9]*\) \(.*\):#define \1 \2 /* \3 */:; \
    s:^->\([^ ]*\) [\$$#]*\([^ ]*\) \(.*\):#define \1 \2 /* \3 */:; \
    s:->::; p;}"
endef

# Use filechk to avoid rebuilds when a header changes, but the resulting file
# does not
define filechk_offsets
    (set -e; \
     echo "#ifndef $2"; \ //输出 #ifndef __GENERIC_ASM_OFFSETS_H__
     echo "#define $2"; \ //输出 #define __GENERIC_ASM_OFFSETS_H__
     echo "/*"; \         //输出 /*
     echo " * DO NOT MODIFY."; \  //输出 * DO NOT MODIFY.
     echo " *"; \                 //输出 *
     echo " * This file was generated by Kbuild"; \    //输出 * This file was generated by Kbuild
     echo " */"; \              //输出 */
     echo ""; \                 //输出 空行
     sed -ne $(sed-y); \       //使用正则表达式解析汇编中符合指定格式的行,并输出
     echo ""; \                //输出 空行
     echo "#endif" )           //输出 #endif
endef
# 1) Generate generic-asm-offsets.h

generic-offsets-file := include/generated/generic-asm-offsets.h

always  := $(generic-offsets-file)  //include/generated/generic-asm-offsets.h
targets := lib/asm-offsets.s

# We use internal kbuild rules to avoid the "is up to date" message from make
lib/asm-offsets.s: lib/asm-offsets.c FORCE                                                 (1)
    $(Q)mkdir -p $(dir $@)           //创建lib目录
    $(call if_changed_dep,cc_s_c)    //把lib/asm-offsets.c编译成lib/asm-offsets.s

$(obj)/$(generic-offsets-file): lib/asm-offsets.s FORCE                                    (2)
    $(call filechk,offsets,__GENERIC_ASM_OFFSETS_H__) //生成include/generated/generic-asm-offsets.h

1. 创建lib目录,把lib/asm-offsets.c编译成lib/asm-offsets.s;

2. 调用filechk生成include/generated/generic-asm-offsets.h:

(1)打印' CHK include/generated/generic-asm-offsets.h'

(2)创建 include/generated/目录

(3)调用filechk_offsets < lib/asm-offsets.s > include/generated/generic-asm-offsets.h.tmp

    ( 3.1) 输出 "#ifndef GENERIC_ASM_OFFSETS_H"

    ( 3.2) 输出 "#define GENERIC_ASM_OFFSETS_H"

    ( 3.3)输出 "/_"

    ( 3.4)输出 "_ DO NOT MODIFY."

    ( 3.5)输出 "_"

    ( 3.6)输出 "_ This file was generated by Kbuild"

    ( 3.7)输出 "*/"

    ( 3.8)输出 空行

    ( 3.9)使用正则表达式解析汇编lib/asm-offsets.s中符合指定格式的行(如下),并输出

    ( 3.10)输出 空行

    ( 3.12)输出 #endif

(4)如果已经存在目标文件include/generated/generic-asm-offsets.h,且比include/generated/generic-asm-offsets.h.tmp更新,则删除后者,保留前者;否则把include/generated/generic-asm-offsets.h.tmp更名为include/generated/generic-asm-offsets.h。

最终生成的include/generated/generic-asm-offsets.h文件如下:

5.1.2 include/generated/asm-offsets.h的编译(架构有关)

# <<<<<<<<<Kbuild>>>>>>>>>
# 2) Generate asm-offsets.h
#

ifneq ($(wildcard $(srctree)/arch/$(ARCH)/lib/asm-offsets.c),)//成立
offsets-file := include/generated/asm-offsets.h
endif

always  += $(offsets-file) //include/generated/asm-offsets.h
targets += arch/$(ARCH)/lib/asm-offsets.s

CFLAGS_asm-offsets.o := -DDO_DEPS_ONLY

# We use internal kbuild rules to avoid the "is up to date" message from make
arch/$(ARCH)/lib/asm-offsets.s: arch/$(ARCH)/lib/asm-offsets.c FORCE          (1)
    $(Q)mkdir -p $(dir $@)           //创建lib目录
    $(call if_changed_dep,cc_s_c)    //把arch/arm/asm-offsets.c编译成arch/arm/asm-offsets.s

$(obj)/$(offsets-file): arch/$(ARCH)/lib/asm-offsets.s FORCE                  (2)
    $(call filechk,offsets,__ASM_OFFSETS_H__)//include/generated/asm-offsets.h

1. 创建arch\arm\lib目录,把arch\arm\lib/asm-offsets.c编译成arch\arm\lib/asm-offsets.s;

2. 调用filechk生成include/generated/asm-offsets.h:

编译过程同上。

最终生成的include/generated/asm-offsets.h文件如下:

6. 构建$(u-boot-dirs)

关于$(u-boot-dirs)的定义在上一篇文中已经讲过,所包含全部需要编译的目录,这里以仅以arch/arm/cpu/armv8 为例,其它雷同。

#  <<<<<<<<<顶层Makefile>>>>>>>>>
u-boot-dirs    := $(patsubst %/,%,$(filter %/, $(libs-y))) tools examples //目标

......

# Handle descending into subdirectories listed in $(vmlinux-dirs)
# Preset locale variables to speed up the build process. Limit locale
# tweaks to this spot to avoid wrong language settings when running
# make menuconfig etc.
# Error messages still appears in the original language

PHONY += $(u-boot-dirs)
$(u-boot-dirs): prepare scripts
    $(Q)$(MAKE) $(build)=$@                                           //规则

$ (Q) $ (MAKE) $ (build)=$@这个命令,引入各个目录下的Kbuild或Makefile,依据Makefile.build中定义的规则构建目标。

● 如果定义了hostprogs-y,则引入Makefile.host,构建目标

● 如果定义了obj-y,依据Makefile.build中的规则构建各个.o文件,并最终链接成build-in.o文件

$(u-boot-dirs)的定义在上文中已经讲过:

arch/arm/cpu  \
arch/arm/cpu/armv8 \
arch/arm/lib \
arch/arm/mach-imx \
board/myzr/common  \
board/myzr/myimx8mm  \
cmd  \
common  \
disk  \
drivers \
drivers/dma  \
drivers/gpio  \
drivers/i2c  \
drivers/mtd \
drivers/mtd/onenand  \
drivers/mtd/spi \
drivers/net  \
drivers/net/phy  \
     .
     .
     .
env  \
fs  \
lib  \
net  \
test \
test/dm

下面以构建arch/arm/cpu/armv8为例:

arch/arm/cpu/armv8 : prepare scripts
    $(Q)$(MAKE) $(build)=$@

其中 $ (build)定义在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

展开为

make -f scripts/basic/Makefile.build obj=arch/arm/cpu/armv8

在Makefile.build中,会引用要编译目录的Makefile(arch/arm/cpu/armv8/Makefile),这点在前文中多次讲到过:

# <<<<<<<<<scripts/Makefile.build>>>>>>>>>
# 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) //arch/arm/cpu/armv8/Makefile
include $(kbuild-file)                                  (1)//include arch/arm/cpu/armv8/Makefile

......

ifneq ($(strip $(lib-y) $(lib-m) $(lib-)),)
lib-target := $(obj)/lib.a                              (2)lib-target :=
endif

ifneq ($(strip $(obj-y) $(obj-m) $(obj-) $(subdir-m) $(lib-target)),)//去空格函数—strip
builtin-target := $(obj)/built-in.o                      (3) builtin-target := arch/arm/cpu/armv8/built-in.o
endif

modorder-target := $(obj)/modules.order

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

1. 引用arch/arm/cpu/armv8/目录下的Makefile

# <<<<<<<<<arch/arm/cpu/armv8/Makefile>>>>>>>>>
extra-y    := start.o

obj-y    += cpu.o
ifndef CONFIG_$(SPL_TPL_)TIMER
obj-y    += generic_timer.o
endif
obj-y    += cache_v8.o
obj-y    += exceptions.o
obj-y    += cache.o
obj-y    += tlb.o
obj-y    += transition.o
obj-y    += fwcall.o
obj-y    += cpu-dt.o
obj-$(CONFIG_ARM_SMCCC)        += smccc-call.o

ifndef CONFIG_SPL_BUILD
obj-$(CONFIG_ARMV8_SPIN_TABLE) += spin_table.o spin_table_v8.o
endif
obj-$(CONFIG_$(SPL_)ARMV8_SEC_FIRMWARE_SUPPORT) += sec_firmware.o sec_firmware_asm.o

obj-$(CONFIG_FSL_LAYERSCAPE) += fsl-layerscape/
obj-$(CONFIG_S32V234) += s32v234/
obj-$(CONFIG_ARCH_ZYNQMP) += zynqmp/
obj-$(CONFIG_TARGET_HIKEY) += hisilicon/
obj-$(CONFIG_ARMV8_PSCI) += psci.o
obj-$(CONFIG_ARCH_SUNXI) += lowlevel_init.o
obj-$(CONFIG_XEN) += xen/

2. lib-target的定义

ifneq ($(strip $(lib-y) $(lib-m) $(lib-)),)
lib-target := $(obj)/lib.a                              (2)lib-target :=
endif

$(lib-y) $(lib-m) $(lib-)在arch/arm/cpu/armv8/Makefile中均未定义,因此lib-target := 。

3. builtin-target的定义

ifneq ($(strip $(obj-y) $(obj-m) $(obj-) $(subdir-m) $(lib-target)),)//去空格函数—strip
builtin-target := $(obj)/built-in.o                      (3) builtin-target := arch/arm/cpu/armv8/built-in.o
endif

综上,对于默认目标__build:

  • KBUILD_BUILTIN为y,在arch/arm/cpu/armv8/Makefile中定义了obj-y,其它为空(注意,如果subdir-m不为空会继续遍历这些子目录)。所以builtin-target=arch/arm/cpu/armv8/built-in.o ,lib-targe=,extra-y=arch/arm/cpu/armv8/start.o ;
  • $(subdir-ym)为空(注意并不是所有的编译目标都是空);
  • $(always)为空;
  • 展开为:
  • __build: arch/arm/cpu/armv8/built-in.o arch/arm/cpu/armv8/start.o
  •     @:

$ (builtin-target)(*/build-in.o)依赖$(obj-y),也就是在arch/arm/cpu/armv8/Makefile中定义的那些.o文件。因此要先构建%.o,再构建%/built-in.o:

# <<<<<<<<<scripts/Makefile.build>>>>>>>>>
cmd_link_o_target = $(if $(strip $(obj-y)),\
              $(LD) $(ld_flags) -r -o $@ $(filter $(obj-y), $^) \
              $(cmd_secanalysis),\
              rm -f $@; $(AR) rcs$(KBUILD_ARFLAGS) $@)

$(builtin-target): $(obj-y) FORCE
    $(call if_changed,link_o_target)

6.1.1 %.o文件的编译

.o文件使用如下规则构建(因为-f指定 scripts/Makefile.build,优先在该文件中寻找规则):

# <<<<<<<<<scripts/Makefile.build>>>>>>>>>
# C (.c) files
# The C file is compiled and updated dependency information is generated.
# (See cmd_cc_o_c + relevant part of rule_cc_o_c)

quiet_cmd_cc_o_c = CC $(quiet_modtag)  $@

ifndef CONFIG_MODVERSIONS //校验符号用,这里我编译时未定义
cmd_cc_o_c = $(CC) $(c_flags) -c -o $@ $<            //重点关注 %.c --> %.o的具体编译命令

else
# When module versioning is enabled the following steps are executed:
# o compile a .tmp_<file>.o from <file>.c
# o if .tmp_<file>.o doesn't contain a __ksymtab version, i.e. does
#   not export symbols, we just rename .tmp_<file>.o to <file>.o and
#   are done.
# o otherwise, we calculate symbol versions using the good old
#   genksyms on the preprocessed source and postprocess them in a way
#   that they are usable as a linker script
# o generate <file>.o from .tmp_<file>.o using the linker to
#   replace the unresolved symbols __crc_exported_symbol with
#   the actual value of the checksum generated by genksyms

cmd_cc_o_c = $(CC) $(c_flags) -c -o $(@D)/.tmp_$(@F) $<
cmd_modversions =                                \
    if $(OBJDUMP) -h $(@D)/.tmp_$(@F) | grep -q __ksymtab; then      \
        $(call cmd_gensymtypes,$(KBUILD_SYMTYPES),$(@:.o=.symtypes)) \
            > $(@D)/.tmp_$(@F:.o=.ver);                   \
                                        \
        $(LD) $(LDFLAGS) -r -o $@ $(@D)/.tmp_$(@F)             \
            -T $(@D)/.tmp_$(@F:.o=.ver);              \
        rm -f $(@D)/.tmp_$(@F) $(@D)/.tmp_$(@F:.o=.ver);        \
    else                                    \
        mv -f $(@D)/.tmp_$(@F) $@;                   \
    fi;
endif

......

define rule_cc_o_c
    $(call echo-cmd,checksrc) $(cmd_checksrc)           \
    $(call echo-cmd,cc_o_c) $(cmd_cc_o_c);                  \
    $(cmd_modversions)                       \
    $(call echo-cmd,record_mcount)                   \
    $(cmd_record_mcount)                         \
    scripts/basic/fixdep $(depfile) $@ '$(call make-cmd,cc_o_c)' >    \
                                                  $(dot-target).tmp;  \
    rm -f $(depfile);                        \
    mv -f $(dot-target).tmp $(dot-target).cmd
endef

# Built-in and composite module parts
$(obj)/%.o: $(src)/%.c $(recordmcount_source) FORCE
    $(call cmd,force_checksrc)
    $(call if_changed_rule,cc_o_c)

quiet_cmd_as_o_S = AS $(quiet_modtag)  $@
cmd_as_o_S       = $(CC) $(a_flags) -c -o $@ $<      //重点关注 %.S --> %.o的具体编译命令

$(obj)/%.o: $(src)/%.S FORCE
    $(call if_changed_dep,as_o_S)

其中CONFIG_MODVERSIONS 宏的作用,请参考: Linux内核编译 CONFIG_MODVERSIONS 作用

执行cmd_cc_o_c定义的命令将.c编译成.o,执行cmd_as_o_S定义的命令将.S编译成.o。

编译打印命令如下:

  CC      arch/arm/cpu/armv8/cpu.o
  CC      arch/arm/cpu/armv8/generic_timer.o
  CC      arch/arm/cpu/armv8/cache_v8.o
  AS      arch/arm/cpu/armv8/exceptions.o
  AS      arch/arm/cpu/armv8/cache.o
  AS      arch/arm/cpu/armv8/tlb.o
  AS      arch/arm/cpu/armv8/transition.o
  CC      arch/arm/cpu/armv8/fwcall.o
  CC      arch/arm/cpu/armv8/cpu-dt.o
  AS      arch/arm/cpu/armv8/start.o

真实执行的完整命令如下:

/home/h/my-work/03_toolchain/gcc-linaro-7.3.1-2018.05-x86_64_aarch64-linux-gnu/bin/aarch64-linux-gnu-gcc -Wp,-MD,arch/arm/cpu/armv8/.cpu.o.d  -nostdinc -isystem /home/h/my-work/03_toolchain/gcc-linaro-7.3.1-2018.05-x86_64_aarch64-linux-gnu/bin/../lib/gcc/aarch64-linux-gnu/7.3.1/include -Iinclude   -I./arch/arm/include -include ./include/linux/kconfig.h -D__KERNEL__ -D__UBOOT__ -Wall -Wstrict-prototypes -Wno-format-security -fno-builtin -ffreestanding -fshort-wchar -Os -fno-stack-protector -fno-delete-null-pointer-checks -g -fstack-usage -Wno-format-nonliteral -Werror=date-time -D__ARM__ -fno-pic -mstrict-align -ffunction-sections -fdata-sections -fno-common -ffixed-r9 -fno-common -ffixed-x18 -pipe -march=armv8-a -mgeneral-regs-only -D__LINUX_ARM_ARCH__=8    -D"KBUILD_STR(s)=#s" -D"KBUILD_BASENAME=KBUILD_STR(cpu)"  -D"KBUILD_MODNAME=KBUILD_STR(cpu)" -c -o arch/arm/cpu/armv8/cpu.o arch/arm/cpu/armv8/cpu.c
/home/h/my-work/03_toolchain/gcc-linaro-7.3.1-2018.05-x86_64_aarch64-linux-gnu/bin/aarch64-linux-gnu-gcc -Wp,-MD,arch/arm/cpu/armv8/.generic_timer.o.d  -nostdinc -isystem /home/h/my-work/03_toolchain/gcc-linaro-7.3.1-2018.05-x86_64_aarch64-linux-gnu/bin/../lib/gcc/aarch64-linux-gnu/7.3.1/include -Iinclude   -I./arch/arm/include -include ./include/linux/kconfig.h -D__KERNEL__ -D__UBOOT__ -Wall -Wstrict-prototypes -Wno-format-security -fno-builtin -ffreestanding -fshort-wchar -Os -fno-stack-protector -fno-delete-null-pointer-checks -g -fstack-usage -Wno-format-nonliteral -Werror=date-time -D__ARM__ -fno-pic -mstrict-align -ffunction-sections -fdata-sections -fno-common -ffixed-r9 -fno-common -ffixed-x18 -pipe -march=armv8-a -mgeneral-regs-only -D__LINUX_ARM_ARCH__=8    -D"KBUILD_STR(s)=#s" -D"KBUILD_BASENAME=KBUILD_STR(generic_timer)"  -D"KBUILD_MODNAME=KBUILD_STR(generic_timer)" -c -o arch/arm/cpu/armv8/generic_timer.o arch/arm/cpu/armv8/generic_timer.c
/home/h/my-work/03_toolchain/gcc-linaro-7.3.1-2018.05-x86_64_aarch64-linux-gnu/bin/aarch64-linux-gnu-gcc -Wp,-MD,arch/arm/cpu/armv8/.cache_v8.o.d  -nostdinc -isystem /home/h/my-work/03_toolchain/gcc-linaro-7.3.1-2018.05-x86_64_aarch64-linux-gnu/bin/../lib/gcc/aarch64-linux-gnu/7.3.1/include -Iinclude   -I./arch/arm/include -include ./include/linux/kconfig.h -D__KERNEL__ -D__UBOOT__ -Wall -Wstrict-prototypes -Wno-format-security -fno-builtin -ffreestanding -fshort-wchar -Os -fno-stack-protector -fno-delete-null-pointer-checks -g -fstack-usage -Wno-format-nonliteral -Werror=date-time -D__ARM__ -fno-pic -mstrict-align -ffunction-sections -fdata-sections -fno-common -ffixed-r9 -fno-common -ffixed-x18 -pipe -march=armv8-a -mgeneral-regs-only -D__LINUX_ARM_ARCH__=8    -D"KBUILD_STR(s)=#s" -D"KBUILD_BASENAME=KBUILD_STR(cache_v8)"  -D"KBUILD_MODNAME=KBUILD_STR(cache_v8)" -c -o arch/arm/cpu/armv8/cache_v8.o arch/arm/cpu/armv8/cache_v8.c
/home/h/my-work/03_toolchain/gcc-linaro-7.3.1-2018.05-x86_64_aarch64-linux-gnu/bin/aarch64-linux-gnu-gcc -Wp,-MD,arch/arm/cpu/armv8/.exceptions.o.d  -nostdinc -isystem /home/h/my-work/03_toolchain/gcc-linaro-7.3.1-2018.05-x86_64_aarch64-linux-gnu/bin/../lib/gcc/aarch64-linux-gnu/7.3.1/include -Iinclude   -I./arch/arm/include -include ./include/linux/kconfig.h -D__KERNEL__ -D__UBOOT__ -D__ASSEMBLY__ -g -D__ARM__ -fno-pic -mstrict-align -ffunction-sections -fdata-sections -fno-common -ffixed-r9 -fno-common -ffixed-x18 -pipe -march=armv8-a -mgeneral-regs-only -D__LINUX_ARM_ARCH__=8   -c -o arch/arm/cpu/armv8/exceptions.o arch/arm/cpu/armv8/exceptions.S
/home/h/my-work/03_toolchain/gcc-linaro-7.3.1-2018.05-x86_64_aarch64-linux-gnu/bin/aarch64-linux-gnu-gcc -Wp,-MD,arch/arm/cpu/armv8/.cache.o.d  -nostdinc -isystem /home/h/my-work/03_toolchain/gcc-linaro-7.3.1-2018.05-x86_64_aarch64-linux-gnu/bin/../lib/gcc/aarch64-linux-gnu/7.3.1/include -Iinclude   -I./arch/arm/include -include ./include/linux/kconfig.h -D__KERNEL__ -D__UBOOT__ -D__ASSEMBLY__ -g -D__ARM__ -fno-pic -mstrict-align -ffunction-sections -fdata-sections -fno-common -ffixed-r9 -fno-common -ffixed-x18 -pipe -march=armv8-a -mgeneral-regs-only -D__LINUX_ARM_ARCH__=8   -c -o arch/arm/cpu/armv8/cache.o
/home/h/my-work/03_toolchain/gcc-linaro-7.3.1-2018.05-x86_64_aarch64-linux-gnu/bin/aarch64-linux-gnu-gcc -Wp,-MD,arch/arm/cpu/armv8/.tlb.o.d  -nostdinc -isystem /home/h/my-work/03_toolchain/gcc-linaro-7.3.1-2018.05-x86_64_aarch64-linux-gnu/bin/../lib/gcc/aarch64-linux-gnu/7.3.1/include -Iinclude   -I./arch/arm/include -include ./include/linux/kconfig.h -D__KERNEL__ -D__UBOOT__ -D__ASSEMBLY__ -g -D__ARM__ -fno-pic -mstrict-align -ffunction-sections -fdata-sections -fno-common -ffixed-r9 -fno-common -ffixed-x18 -pipe -march=armv8-a -mgeneral-regs-only -D__LINUX_ARM_ARCH__=8   -c -o arch/arm/cpu/armv8/tlb.o
/home/h/my-work/03_toolchain/gcc-linaro-7.3.1-2018.05-x86_64_aarch64-linux-gnu/bin/aarch64-linux-gnu-gcc -Wp,-MD,arch/arm/cpu/armv8/.transition.o.d  -nostdinc -isystem /home/h/my-work/03_toolchain/gcc-linaro-7.3.1-2018.05-x86_64_aarch64-linux-gnu/bin/../lib/gcc/aarch64-linux-gnu/7.3.1/include -Iinclude   -I./arch/arm/include -include ./include/linux/kconfig.h -D__KERNEL__ -D__UBOOT__ -D__ASSEMBLY__ -g -D__ARM__ -fno-pic -mstrict-align -ffunction-sections -fdata-sections -fno-common -ffixed-r9 -fno-common -ffixed-x18 -pipe -march=armv8-a -mgeneral-regs-only -D__LINUX_ARM_ARCH__=8   -c -o arch/arm/cpu/armv8/transition.o
/home/h/my-work/03_toolchain/gcc-linaro-7.3.1-2018.05-x86_64_aarch64-linux-gnu/bin/aarch64-linux-gnu-gcc -Wp,-MD,arch/arm/cpu/armv8/.fwcall.o.d  -nostdinc -isystem /home/h/my-work/03_toolchain/gcc-linaro-7.3.1-2018.05-x86_64_aarch64-linux-gnu/bin/../lib/gcc/aarch64-linux-gnu/7.3.1/include -Iinclude   -I./arch/arm/include -include ./include/linux/kconfig.h -D__KERNEL__ -D__UBOOT__ -Wall -Wstrict-prototypes -Wno-format-security -fno-builtin -ffreestanding -fshort-wchar -Os -fno-stack-protector -fno-delete-null-pointer-checks -g -fstack-usage -Wno-format-nonliteral -Werror=date-time -D__ARM__ -fno-pic -mstrict-align -ffunction-sections -fdata-sections -fno-common -ffixed-r9 -fno-common -ffixed-x18 -pipe -march=armv8-a -mgeneral-regs-only -D__LINUX_ARM_ARCH__=8    -D"KBUILD_STR(s)=#s" -D"KBUILD_BASENAME=KBUILD_STR(fwcall)"  -D"KBUILD_MODNAME=KBUILD_STR(fwcall)" -c -o arch/arm/cpu/armv8/fwcall.o
/home/h/my-work/03_toolchain/gcc-linaro-7.3.1-2018.05-x86_64_aarch64-linux-gnu/bin/aarch64-linux-gnu-gcc -Wp,-MD,arch/arm/cpu/armv8/.cpu-dt.o.d  -nostdinc -isystem /home/h/my-work/03_toolchain/gcc-linaro-7.3.1-2018.05-x86_64_aarch64-linux-gnu/bin/../lib/gcc/aarch64-linux-gnu/7.3.1/include -Iinclude   -I./arch/arm/include -include ./include/linux/kconfig.h -D__KERNEL__ -D__UBOOT__ -Wall -Wstrict-prototypes -Wno-format-security -fno-builtin -ffreestanding -fshort-wchar -Os -fno-stack-protector -fno-delete-null-pointer-checks -g -fstack-usage -Wno-format-nonliteral -Werror=date-time -D__ARM__ -fno-pic -mstrict-align -ffunction-sections -fdata-sections -fno-common -ffixed-r9 -fno-common -ffixed-x18 -pipe -march=armv8-a -mgeneral-regs-only -D__LINUX_ARM_ARCH__=8    -D"KBUILD_STR(s)=#s" -D"KBUILD_BASENAME=KBUILD_STR(cpu_dt)"  -D"KBUILD_MODNAME=KBUILD_STR(cpu_dt)" -c -o arch/arm/cpu/armv8/cpu-dt.o
/home/h/my-work/03_toolchain/gcc-linaro-7.3.1-2018.05-x86_64_aarch64-linux-gnu/bin/aarch64-linux-gnu-gcc -Wp,-MD,arch/arm/cpu/armv8/.start.o.d  -nostdinc -isystem /home/h/my-work/03_toolchain/gcc-linaro-7.3.1-2018.05-x86_64_aarch64-linux-gnu/bin/../lib/gcc/aarch64-linux-gnu/7.3.1/include -Iinclude   -I./arch/arm/include -include ./include/linux/kconfig.h -D__KERNEL__ -D__UBOOT__ -D__ASSEMBLY__ -g -D__ARM__ -fno-pic -mstrict-align -ffunction-sections -fdata-sections -fno-common -ffixed-r9 -fno-common -ffixed-x18 -pipe -march=armv8-a -mgeneral-regs-only -D__LINUX_ARM_ARCH__=8   -c -o arch/arm/cpu/armv8/start.o

-wp,-MD 会生成相应的依赖文件。-fno-pic是用来生成位置有关代码。

6.1.2 %/build-in.o文件的编译

最后,将编译出来的.o文件使用cmd_link_o_target链接成arch/arm/cpu/armv8/build-in.o,注意参数-r 表示。

编译打印如下:

  LD      arch/arm/cpu/armv8/built-in.o

真实执行的完整命令如下:

/home/h/my-work/03_toolchain/gcc-linaro-7.3.1-2018.05-x86_64_aarch64-linux-gnu/bin/aarch64-linux-gnu-ld.bfd     -r -o arch/arm/cpu/armv8/built-in.o arch/arm/cpu/armv8/cpu.o arch/arm/cpu/armv8/generic_timer.o arch/arm/cpu/armv8/cache_v8.o arch/arm/cpu/armv8/exceptions.o arch/arm/cpu/armv8/cache.o arch/arm/cpu/armv8/tlb.o arch/arm/cpu/armv8/transition.o arch/arm/cpu/armv8/fwcall.o arch/arm/cpu/armv8/cpu-dt.o

注意链接参数-r' --relocateable' 产生可重定位的输出, 比如,产生一个输出文件它可再次作为'ld'的输入。这经常被叫做"部分连接"。

其他目录的的执行过程也是类似的,就不做进一步分析了

7. 构建$ (u-boot-init)

注意在编译arch/arm/cpu/armv8/目录时,同时生成了arch/arm/cpu/armv8/start.o,这是u-boot的依赖 $ (u-boot-init)==$(head-y)

8. 构建$(u-boot-dirs)

注意在编译$ (u-boot-dirs)时,同时生成了 */built-in.o ,这是u-boot的依赖 $ (u-boot-main)==$(libs-y)

9. 构建u-boot.lds

u-boot.lds的定义位于顶层Makefile中(参见UBOOT编译--- UBOOT编译过程目标依赖分析(八) - 5.3 依赖u-boot.lds)。上文已经讲过,如果没有定义LDSCRIPT和CONFIG_SYS_LDSCRIPT,则默认使用u-boot自带的lds文件,包括board/$ (BOARDDIR)和$ (CPUDIR)目录下定制的针对board或cpu的lds文件;如果没有定制的lds文件,则采用arch/$(ARCH)/cpu目录下默认的lds文件。针对我的开发板,u-boot.lds = arch/arm/cpu/armv8/u-boot.lds。

规则如下:

# <<<<<<<<<顶层config.mk>>>>>>>>>
quiet_cmd_cpp_lds = LDS     $@
cmd_cpp_lds = $(CPP) -Wp,-MD,$(depfile) $(cpp_flags) $(LDPPFLAGS) \
        -D__ASSEMBLY__ -x assembler-with-cpp -P -o $@ $<

u-boot.lds: $(LDSCRIPT) prepare FORCE
    $(call if_changed_dep,cpp_lds)

编译打印如下:

在这里插入代码片

真实执行的完整命令如下:

/home/h/my-work/03_toolchain/gcc-linaro-7.3.1-2018.05-x86_64_aarch64-linux-gnu/bin/aarch64-linux-gnu-gcc -E -Wp,-MD,./.u-boot.lds.d -D__KERNEL__ -D__UBOOT__   -D__ARM__           -fno-pic  -mstrict-align  -ffunction-sections -fdata-sections -fno-common -ffixed-r9    -fno-common -ffixed-x18 -pipe -march=armv8-a -mgeneral-regs-only -D__LINUX_ARM_ARCH__=8   -Iinclude   -I./arch/arm/include -include ./include/linux/kconfig.h  -nostdinc -isystem /home/h/my-work/03_toolchain/gcc-linaro-7.3.1-2018.05-x86_64_aarch64-linux-gnu/bin/../lib/gcc/aarch64-linux-gnu/7.3.1/include -ansi -include ./include/u-boot/u-boot.lds.h -DCPUDIR=arch/arm/cpu/armv8  -D__ASSEMBLY__ -x assembler-with-cpp -P -o u-boot.lds arch/arm/cpu/armv8/u-boot.lds

编译选项'-E'、'-x'、-P(具体解释见本文末尾参考章节)。该编译过程主要是为了展开arch/arm/cpu/armv8/u-boot.lds中的头文件中的宏定义重点关注引用的,这个头文件是我们在编译的过程中产生的include/config.h,里面又会引用其它头文件,都会递归展开并进行对应的宏替换。这里我截取了一部分,如下:

10. u-boot编译

# <<<<<<<<<顶层顶层Makefile>>>>>>>>>
# Rule to link u-boot
# May be overridden by arch/$(ARCH)/config.mk
quiet_cmd_u-boot__ ?= LD      $@
      cmd_u-boot__ ?= $(LD) $(LDFLAGS) $(LDFLAGS_u-boot) -o $@ \
      -T u-boot.lds $(u-boot-init)                             \
      --start-group $(u-boot-main) --end-group                 \
      $(PLATFORM_LIBS) -Map u-boot.map;                        \
      $(if $(ARCH_POSTLINK), $(MAKE) -f $(ARCH_POSTLINK) $@, true)

quiet_cmd_smap = GEN     common/system_map.o
cmd_smap = \
    smap=`$(call SYSTEM_MAP,u-boot) | \
        awk '$$2 ~ /[tTwW]/ {printf $$1 $$3 "\\\\000"}'` ; \
    $(CC) $(c_flags) -DSYSTEM_MAP="\"$${smap}\"" \
        -c $(srctree)/common/system_map.c -o common/system_map.o

u-boot:    $(u-boot-init) $(u-boot-main) u-boot.lds FORCE
    +$(call if_changed,u-boot__)          //uboot的规则
ifeq ($(CONFIG_KALLSYMS),y)               //未定义
    $(call cmd,smap)
    $(call cmd,u-boot__) common/system_map.o
endif

目标u-boot的依赖:$ (u-boot-init)、$ (u-boot-main)、u-boot.lds、FORCE在前面小节已经分析过。

/home/h/my-work/03_toolchain/gcc-linaro-7.3.1-2018.05-x86_64_aarch64-linux-gnu/bin/aarch64-linux-gnu-ld.bfd   -pie  --gc-sections -Bstatic  --no-dynamic-linker -Ttext 0x40200000 -o u-boot -T u-boot.lds arch/arm/cpu/armv8/start.o --start-group  arch/arm/cpu/built-in.o  arch/arm/cpu/armv8/built-in.o  arch/arm/lib/built-in.o  arch/arm/mach-imx/built-in.o  board/myzr/common/built-in.o  board/myzr/myimx8mm/built-in.o  cmd/built-in.o  common/built-in.o  disk/built-in.o  drivers/built-in.o  drivers/dma/built-in.o  drivers/gpio/built-in.o  drivers/i2c/built-in.o  drivers/mtd/built-in.o  drivers/mtd/onenand/built-in.o  drivers/mtd/spi/built-in.o  drivers/net/built-in.o  drivers/net/phy/built-in.o  drivers/pci/built-in.o  drivers/power/built-in.o  drivers/power/battery/built-in.o  drivers/power/domain/built-in.o  drivers/power/fuel_gauge/built-in.o  drivers/power/mfd/built-in.o  drivers/power/pmic/built-in.o  drivers/power/regulator/built-in.o  drivers/serial/built-in.o  drivers/spi/built-in.o  drivers/usb/cdns3/built-in.o  drivers/usb/common/built-in.o  drivers/usb/dwc3/built-in.o  drivers/usb/emul/built-in.o  drivers/usb/eth/built-in.o  drivers/usb/gadget/built-in.o  drivers/usb/gadget/udc/built-in.o  drivers/usb/host/built-in.o  drivers/usb/musb-new/built-in.o  drivers/usb/musb/built-in.o  drivers/usb/phy/built-in.o  drivers/usb/ulpi/built-in.o  env/built-in.o  fs/built-in.o  lib/built-in.o  net/built-in.o  test/built-in.o  test/dm/built-in.o --end-group -L /home/h/my-work/03_toolchain/gcc-linaro-7.3.1-2018.05-x86_64_aarch64-linux-gnu/bin/../lib/gcc/aarch64-linux-gnu/7.3.1 -lgcc -Map u-boot.map;  true
  • -pie: 生成position-independent executable (ET_EXEC)。
  • -Bstatic:在-L指定的目录列表中查找 xxx.a
  • --no-dynamic-linker : Produce an executable with no program interpreter header
  • -T :指定链接脚本就是u-boot.lds
  • –start-group archives --end-group :正常情况,链接的时候库文件只会按它们出现在命令行的顺序搜索一遍,如果包里有未定义的引用标号,而且该包还被放在命令行的后面,这样链接器就无法解决该标号的引用问题。通过给包分组,这些包可以被循环搜索直到所有的引用都可以解决为止。使用该选项将降低性能。只有在无法避免多个包之间互相引用的情况下才使用。
  • -Ttext 0x40200000 ’-T’命令行选项只能用于设置 “text” 、“data” 和 “bss” 段的基址,这里是把text段基址设为0x40200000。
  • -Map FILE :Write a map file。主要是一些段的信息。

11. 构建include/config/uboot.release

参见:UBOOT编译--- UBOOT的$(version_h) $(timestamp_h)(七) - 3.1.1 依赖include/config/uboot.release

12. 构建outputmakefile

参见:UBOOT编译--- make xxx_deconfig过程详解(一) - 4.2 依赖 outputmakefile

13. 构建$(version_h)、 $(timestamp_h)

参见:UBOOT编译--- UBOOT的$(version_h) $(timestamp_h)(七)

14. 构建tool

没什么好讲的,就是编译一些后面会使用的工具(tools/bmp_logo、 tools/gen_eth_addr、 tools/gen_ethaddr_crc、 tools/img2srec、 tools/mkenvimage 、tools/dumpimage 、tools/mkimage、 tools/proftool 、tools/relocate-rela 、tools/fdtgrep),编译规则参见前面的章节,套路是一模一样的。

15. cfg

# <<<<<<<<<scripts/Makefile.autoconf>>>>>>>>>
u-boot.cfg: include/config.h FORCE
    $(call cmd,u_boot_cfg)

# <<<<<<<<<顶层顶层Makefile>>>>>>>>>
u-boot.cfg spl/u-boot.cfg tpl/u-boot.cfg: include/config.h FORCE
    $(Q)$(MAKE) -f $(srctree)/scripts/Makefile.autoconf $(@) //指定目标u-boot.cfg,定义在scripts/Makefile.autoconf中

cfg: u-boot.cfg

参见:UBOOT编译--- include/config.h、 include/autoconf.mk、include/autoconf.mk.dep、u-boot.cfg(三)

16. u-boot-nodtb.bin

# <<<<<<<<<顶层Makefile>>>>>>>>>
u-boot-nodtb.bin: u-boot FORCE
    $(call if_changed,objcopy)
    $(call DO_STATIC_RELA,$<,$@,$(CONFIG_SYS_TEXT_BASE))
    $(BOARD_SIZE_CHECK)

16.1.1 if_changed定义

# <<<<<<<<<scripts/Kbuild.include>>>>>>>>>
# Execute command if command has changed or prerequisite(s) are updated.
# //如果命令已更改或prerequisites已更新,请执行命令
if_changed = $(if $(strip $(any-prereq) $(arg-check)),                       \
    @set -e;                                                             \
    $(echo-cmd) $(cmd_$(1));                                             \
    printf '%s\n' 'cmd_$@ := $(make-cmd)' > $(dot-target).cmd)

1. $(strip $(any-prereq) $(arg-check) )

(1) any-prereq定义

# <<<<<<<<<scripts/Kbuild.include>>>>>>>>>
# Find any prerequisites that is newer than target or that does not exist.
# PHONY targets skipped in both cases.
//查找比目标更新或不存在的任何prerequisites。
 any-prereq = $(filter-out $(PHONY),$?) $(filter-out $(PHONY) $(wildcard $^),$^)//这里为u-boot
  • $ ? 表示所有比目标还要新的依赖文件;
  • $ ^ 表示所有的依赖文件;

$(filter-out $ (PHONY), $?)就是过滤掉比目标还要新的依赖文件中的伪目标;

$ (filter-out $ (PHONY) $ (wildcard $ ^ ), $^)表示过滤掉所有的依赖文件中的伪目标与存在的依赖文件。

(2) arg-check定义:

# <<<<<<<<<scripts/Kbuild.include>>>>>>>>>
ifneq ($(KBUILD_NOCMDDEP),1)
# Check if both arguments has same arguments. Result is empty string if equal.
# User may override this check using make KBUILD_NOCMDDEP=1
//检查两个参数是否具有相同的参数。如果相等,则结果为空字符串。用户可以使用make KBUILD\u NOCMDDEP=1覆盖此检查
    arg-check = $(strip $(filter-out $(cmd_$(1)), $(cmd_$@)) \
     $(filter-out $(cmd_$@),   $(cmd_$(1))) )
else
    arg-check = $(if $(strip $(cmd_$@)),,1)
endif

KBUILD_NOCMDDEP是在make命令行中定义,我们并没有定义,所以:

arg-check = $(strip $(filter-out $(cmd_$(1)), $(cmd_$@)) $(filter-out $(cmd_$@), $(cmd_$(1))) )

$ (filter-out $ (cmd_ $ (1)), $ (cmd_ $@)) 表示过滤掉 $(cmd_ $@)中符合 $(cmd_ $(1))的项。 $(1)表示if_changed函数的第一个参数objcopy, $@表示目标文件u-boot-nodtb.bin。cmd_ $(1)为cmd_objcopy,cmd_ $@为cmd_u-boot-nodtb.bin。

  • cmd_u-boot-nodtb.bin并没有定义,所以 $(filter-out $(cmd_ $(1)), $(cmd_ $@))为空;

  • cmd_objcopy 在顶层Makefile中定义:

    <<<<<<<<<顶层Makefile>>>>>>>>>

    Normally we fill empty space with 0xff

    quiet_cmd_objcopy = OBJCOPY $@
    cmd_objcopy = $(OBJCOPY) --gap-fill=0xff $(OBJCOPYFLAGS) <br /> $(OBJCOPYFLAGS_$(@F)) $< $@

所以arg-check = $ (filter-out $ (cmd_$ @), $ (cmd_$ (1))) = $(OBJCOPY) --gap-fill=0xff $(OBJCOPYFLAGS)

$(OBJCOPYFLAGS_ $(@F)) $< $@。

因为 $(any-prereq) $(arg-check)都为非空,所以if_changed展开为:

if_changed = @set -e;   \ /如果任何语句的执行结果不是true则应该退出
    $(echo-cmd) $(cmd_$(1));                                             \
    printf '%s\n' 'cmd_$@ := $(make-cmd)' > $(dot-target).cmd)

16.1.2 $(echo-cmd) $(cmd_ $(1))等价于 $(echo-cmd) $(cmd_objcopy)

1. $(echo-cmd)定义

# <<<<<<<<<scripts/Kbuild.include>>>>>>>>>
# echo command.
# Short version is used, if $(quiet) equals `quiet_', otherwise full one.
echo-cmd = $(if $($(quiet)cmd_$(1)),\
    echo '  $(call escsq,$($(quiet)cmd_$(1)))$(echo-why)';)

quiet=quiet_,在顶层Makefile分析过(当然如果你想看到更详细的打印,您可以通过传入V值,来改变), $(cmd_objcopy)上面分析过,存在,所以:

echo-cmd = echo '  $(call escsq,$(cmd_objcopy))$(echo-why)';

在scripts/Kbuild.include中:

# <<<<<<<<<scripts/Kbuild.include>>>>>>>>>
# Escape single quote for use in echo statements
escsq = $(subst $(squote),'\$(squote)',$1)
ifeq ($(KBUILD_VERBOSE),2)
why =                                                                        \
    $(if $(filter $@, $(PHONY)),- due to target is PHONY,                    \
        $(if $(wildcard $@),                                                 \
            $(if $(strip $(any-prereq)),- due to: $(any-prereq),             \
                $(if $(arg-check),                                           \
                    $(if $(cmd_$@),- due to command line change,             \
                        $(if $(filter $@, $(targets)),                       \
                            - due to missing .cmd file,                      \
                            - due to $(notdir $@) not in $$(targets)         \
                         )                                                   \
                     )                                                       \
                 )                                                           \
             ),                                                              \
             - due to target missing                                         \
         )                                                                   \
     )

echo-why = $(call escsq, $(strip $(why)))
endif

KBUILD_VERBOSE一般我们会采用默认值0(需要调试编译除外),所以 echo-why 为空。

2. $ (cmd_$(1))定义

# <<<<<<<<<顶层Makefile>>>>>>>>>
# Normally we fill empty space with 0xff
quiet_cmd_objcopy = OBJCOPY $@
cmd_objcopy = $(OBJCOPY) --gap-fill=0xff $(OBJCOPYFLAGS) \
    $(OBJCOPYFLAGS_$(@F)) $< $@       //$(OBJCOPYFLAGS_$(@F)) = OBJCOPYFLAGS_u-boot-nodtb.bin
//$(@F):表示"$@"的文件部分,如果"$@"值是"dir/foo.o",那么"$(@F)"就是"foo.o","$(@F)"相当于函数"$(notdir $@)"

(1) $(OBJCOPYFLAGS)定义在顶层config.mk和arch/ $(ARCH)/config.mk(arch/arm/config.mk)中

# <<<<<<<<<顶层config.mk>>>>>>>>>
OBJCOPYFLAGS :=

# <<<<<<<<<arch/arm/config.mk>>>>>>>>>
# limit ourselves to the sections we want in the .bin.
ifdef CONFIG_ARM64  //定义
OBJCOPYFLAGS += -j .text -j .secure_text -j .secure_data -j .rodata -j .data \
        -j .u_boot_list -j .rela.dyn -j .got -j .got.plt \
        -j .binman_sym_table
else
OBJCOPYFLAGS += -j .text -j .secure_text -j .secure_data -j .rodata -j .hash \
        -j .data -j .got -j .got.plt -j .u_boot_list -j .rel.dyn \
        -j .binman_sym_table
endif

# if a dtb section exists we always have to include it
# there are only two cases where it is generated
# 1) OF_EMBEDED is turned on
# 2) unit tests include device tree blobs
OBJCOPYFLAGS += -j .dtb.init.rodata

(2) OBJCOPYFLAGS_u-boot-nodtb.bin定义在顶层Makefile中

# <<<<<<<<<顶层Makefile>>>>>>>>>
OBJCOPYFLAGS_u-boot-nodtb.bin := -O binary \
        $(if $(CONFIG_X86_16BIT_INIT),-R .start16 -R .resetvec)

16.1.3 编译时具体打印

/home/h/my-work/03_toolchain/gcc-linaro-7.3.1-2018.05-x86_64_aarch64-linux-gnu/bin/aarch64-linux-gnu-objcopy --gap-fill=0xff  -j .text -j .secure_text -j .secure_data -j .rodata -j .data -j .u_boot_list -j .rela.dyn -j .got -j .got.plt -j .binman_sym_table -j .dtb.init.rodata -j .efi_runtime -j .efi_runtime_rel -O binary  u-boot u-boot-nodtb.bin

整个编译过程就是把u-boot中的指定段拷贝u-boot-nodtb.bin中。

objcopy的功能:将目标文件的一部分或者全部内容拷贝到另外一个目标文件中,或者实现目标文件的格式转换。

  • j sectionname , --only-section=sectionname : 只将由 sectionname 指定的 section 拷贝到输出文件,可以多次指定,并且注意如果使用不当会导致输出文件不可用。

    -O bfdname :--output-target= bfdname 使用指定的格式来写输出文件(即目标文件),bfdname是BFD库中描述的标准格式名。

# <<<<<<<<<顶层Makefile>>>>>>>>>
//静态应用RELA-style的重定位(目前仅 arm64)这对于需要在原始二进制文件上执行静态重定位的 arm64 很有用,但某些模拟器只接受 ELF 文件(但不执行重定位)。
# Statically apply RELA-style relocations (currently arm64 only)
# This is useful for arm64 where static relocation needs to be performed on
# the raw binary, but certain simulators only accept an ELF file (but don't
# do the relocation).
ifneq ($(CONFIG_STATIC_RELA),)
# $(1) is u-boot ELF, $(2) is u-boot bin, $(3) is text base
DO_STATIC_RELA = \
    start=$$($(NM) $(1) | grep __rel_dyn_start | cut -f 1 -d ' '); \
    end=$$($(NM) $(1) | grep __rel_dyn_end | cut -f 1 -d ' '); \
    tools/relocate-rela $(2) $(3) $$start $$end
else
DO_STATIC_RELA =
endif

编译时具体打印:

start=$(/home/h/my-work/03_toolchain/gcc-linaro-7.3.1-2018.05-x86_64_aarch64-linux-gnu/bin/aarch64-linux-gnu-nm u-boot | grep __rel_dyn_start | cut -f 1 -d ' '); end=$(/home/h/my-work/03_toolchain/gcc-linaro-7.3.1-2018.05-x86_64_aarch64-linux-gnu/bin/aarch64-linux-gnu-nm u-boot | grep __rel_dyn_end | cut -f 1 -d ' '); tools/relocate-rela u-boot-nodtb.bin 0x40200000 $start $end

1. aarch64-linux-gnu-nm u-boot | grep __rel_dyn_start | cut -f 1 -d ' '

  • nm : 列出指定文件的符号表(下图只截取一点);

  • grep __rel_dyn_start :找到符号grep __rel_dyn_start

  • cut -f 1 -d ' ' :取出第1列,分隔符为' '

2. aarch64-linux-gnu-nm u-boot | grep __rel_dyn_end | cut -f 1 -d ' '

  • nm : 列出指定文件的符号表(下图只截取一点);

  • grep __rel_dyn_end:找到符号grep __rel_dyn_end

  • cut -f 1 -d ' ' :取出第1列,分隔符为' '

    3. tools/relocate-rela u-boot-nodtb.bin 0x40200000 $start $end

    重定位。

    <<<<<<<<<顶层Makefile>>>>>>>>>

    ifneq ($(CONFIG_BOARD_SIZE_LIMIT),)
    BOARD_SIZE_CHECK = <br /> @actual=wc -c $@ | awk '{print $$1}'; <br /> limit=printf "%d" $(CONFIG_BOARD_SIZE_LIMIT); <br /> if test $$actual -gt $$limit; then <br /> echo "$@ exceeds file size limit:" >&2 ; <br /> echo " limit: $$limit bytes" >&2 ; <br /> echo " actual: $$actual bytes" >&2 ; <br /> echo " excess: $$((actual - limit)) bytes" >&2; <br /> exit 1; <br /> fi
    else
    BOARD_SIZE_CHECK =
    endif

如果有定义CONFIG_BOARD_SIZE_LIMIT,则检查编译出的目标文件是否超过最大值;如果没有定义,则此项为空。

17. dts/dt.dtb

# <<<<<<<<<顶层Makefile>>>>>>>>>
dts/dt.dtb: u-boot
    $(Q)$(MAKE) $(build)=dts dtbs  //规则

规则展开为:make -f $(srctree)/scripts/Makefile.build obj=dts dtbs。指定目标dtbs,在Makefile.build中会引用dts目录下的Makefile

# <<<<<<<<<scripts/Makefile.build>>>>>>>>>
PHONY := __build
__build:

# The filename Kbuild has precedence over Makefile
kbuild-dir := $(if $(filter /%,$(src)),$(src),$(srctree)/$(src))   //   dts/
kbuild-file := $(if $(wildcard $(kbuild-dir)/Kbuild),$(kbuild-dir)/Kbuild,$(kbuild-dir)/Makefile) //   dts/Makefile
include $(kbuild-file)                                   (1)//include dts/Makefile 

......

include scripts/Makefile.lib   //

......

dts目录下的Makefile内容有目标dtbs的定义:

# <<<<<<<<<dts/Makefile >>>>>>>>>
DEVICE_TREE ?= $(CONFIG_DEFAULT_DEVICE_TREE:"%"=%) //.config:193:CONFIG_DEFAULT_DEVICE_TREE="myimx8mmek240-8mm"
ifeq ($(DEVICE_TREE),)
DEVICE_TREE := unset
endif

ARCH_PATH := arch/$(ARCH)/dts //arch/arm/dts
dtb_depends := arch-dtbs

ifneq ($(EXT_DTB),)
DTB := $(EXT_DTB)
else
DTB := $(ARCH_PATH)/$(DEVICE_TREE).dtb  //arch/arm/dts/myimx8mmek240-8mm.dtb
dtb_depends += $(DTB:.dtb=.dts)         //dtb_depends += arch/arm/dts/myimx8mmek240-8mm.dts
endif

$(obj)/dt-spl.dtb: $(DTB) $(objtree)/tools/fdtgrep FORCE //关注dts/dt-spl.dtb
    $(call if_changed,fdtgrep)

$(obj)/dt.dtb: $(DTB) FORCE     //关注dts/dt.dtb
    $(call if_changed,shipped)

targets += dt.dtb dt-spl.dtb

$(DTB): $(dtb_depends)
ifeq ($(EXT_DTB),)
    $(Q)$(MAKE) $(build)=$(ARCH_PATH) $@
endif
    $(Q)test -e $@ || (                       \
    echo >&2;                           \
    echo >&2 "Device Tree Source is not correctly specified.";  \
    echo >&2 "Please define 'CONFIG_DEFAULT_DEVICE_TREE'";      \
    echo >&2 "or build with 'DEVICE_TREE=<device_tree>' argument";  \
    echo >&2;                           \
    /bin/false)

arch-dtbs:
    $(Q)$(MAKE) $(build)=$(ARCH_PATH) dtbs

.SECONDARY: $(obj)/dt.dtb.S $(obj)/dt-spl.dtb.S

ifeq ($(CONFIG_SPL_BUILD),y)
obj-$(CONFIG_OF_EMBED) := dt-spl.dtb.o
# support "out-of-tree" build for dtb-spl
$(obj)/dt-spl.dtb.o: $(obj)/dt-spl.dtb.S FORCE
    $(call if_changed_dep,as_o_S)
else
obj-$(CONFIG_OF_EMBED) := dt.dtb.o
endif

dtbs: $(obj)/dt.dtb $(obj)/dt-spl.dtb   //关注
    @:

clean-files := dt.dtb.S dt-spl.dtb.S

# Let clean descend into dts directories
subdir- += ../arch/arm/dts ../arch/microblaze/dts ../arch/mips/dts ../arch/sandbox/dts ../arch/x86/dts
......

可以看到目标dtbs依赖于$(obj)/dt.dtb 和 $(obj)/dt-spl.dtb ,且这两个依赖又依赖于 $(DTB),

ARCH_PATH := arch/$(ARCH)/dts //arch/arm/dts
dtb_depends := arch-dtbs

ifneq ($(EXT_DTB),)
DTB := $(EXT_DTB)
else
DTB := $(ARCH_PATH)/$(DEVICE_TREE).dtb  //arch/arm/dts/myimx8mmek240-8mm.dtb
dtb_depends += $(DTB:.dtb=.dts)         //dtb_depends += arch/arm/dts/myimx8mmek240-8mm.dts
endif
$(DTB): $(dtb_depends)
ifeq ($(EXT_DTB),)
    $(Q)$(MAKE) $(build)=$(ARCH_PATH) $@//make -f $(srctree)/scripts/Makefile.build obj=arch/arm/dts arch/arm/dts/myimx8mmek240-8mm.dtb
endif
    $(Q)test -e $@ || (                       \
    echo >&2;                           \
    echo >&2 "Device Tree Source is not correctly specified.";  \
    echo >&2 "Please define 'CONFIG_DEFAULT_DEVICE_TREE'";      \
    echo >&2 "or build with 'DEVICE_TREE=<device_tree>' argument";  \
    echo >&2;                           \
    /bin/false)

arch-dtbs:
    $(Q)$(MAKE) $(build)=$(ARCH_PATH) dtbs//make -f $(srctree)/scripts/Makefile.build obj=arch/arm/dts dtbs

17.1.1 $(DTB)的依赖arch-dtbs和arch/arm/dts/myimx8mmek240-8mm.dts

1. arch-dtbs

规则就是执行:make -f $(srctree)/scripts/Makefile.build obj=arch/arm/dts dtbs命令。目标dtbs定义在arch/arm/dts/Makefile中

# <<<<<<<<<scripts/Makefile.build>>>>>>>>>
# The filename Kbuild has precedence over Makefile
kbuild-dir := $(if $(filter /%,$(src)),$(src),$(srctree)/$(src))   //   arch/arm/dts
kbuild-file := $(if $(wildcard $(kbuild-dir)/Kbuild),$(kbuild-dir)/Kbuild,$(kbuild-dir)/Makefile) //   arch/arm/dts /Makefile
include $(kbuild-file)                                   //include arch/arm/dts /Makefile 

......

include scripts/Makefile.lib   //要关注这个引用。$(obj)/%.dtb定义在这里面
......

# <<<<<<<<<arch/arm/dts/Makefile >>>>>>>>>
dtb-$(CONFIG_AT91FAMILY) += at91sam9260-smartweb.dtb \
    at91sam9g20-taurus.dtb \
    at91sam9g45-corvus.dtb \
......
// $(dtb-y)为各种*.dtb的集合
......

PHONY += dtbs
dtbs: $(addprefix $(obj)/, $(dtb-y))  //dtbs: $(obj)/*.dtb
    @:

这里dtbs又依赖于$(obj)/*.dtb。这个目标不是在arch/arm/dts/Makefile中定义,而是在scripts/Makefile.lib中

# <<<<<<<<<scripts/Makefile.lib >>>>>>>>>
quiet_cmd_dtc = DTC     $@
# Modified for U-Boot
# Bring in any U-Boot-specific include at the end of the file
cmd_dtc = mkdir -p $(dir ${dtc-tmp}) ; \
    (cat $<; $(if $(u_boot_dtsi),echo '\#include "$(u_boot_dtsi)"')) > $(pre-tmp); \
    $(CPP) $(dtc_cpp_flags) -x assembler-with-cpp -o $(dtc-tmp) $(pre-tmp) ; \
    $(DTC) -O dtb -o $@ -b 0 \
        -i $(dir $<) $(DTC_FLAGS) \
        -d $(depfile).dtc.tmp $(dtc-tmp) ; \
    cat $(depfile).pre.tmp $(depfile).dtc.tmp > $(depfile)

$(obj)/%.dtb: $(src)/%.dts FORCE
    $(call if_changed_dep,dtc)

没什么好讲的,就是调用scripts/dtc/dtc 工具生成对应的dtb文件,同时生成*.d文件。

具体编译过程如下:

make -f ./scripts/Makefile.build obj=arch/arm/dts dtbs
  mkdir -p arch/arm/dts/ ; (cat arch/arm/dts/myimx8mek314-8mq.dts; ) > arch/arm/dts/.myimx8mek314-8mq.dtb.pre.tmp; /home/h/my-work/03_toolchain/gcc-linaro-7.3.1-2018.05-x86_64_aarch64-linux-gnu/bin/aarch64-linux-gnu-gcc -E -Wp,-MD,arch/arm/dts/.myimx8mek314-8mq.dtb.d.pre.tmp -nostdinc -I./arch/arm/dts -I./arch/arm/dts/include -Iinclude -I./include -I./arch/arm/include -include ./include/linux/kconfig.h -D__ASSEMBLY__ -undef -D__DTS__ -x assembler-with-cpp -o arch/arm/dts/.myimx8mek314-8mq.dtb.dts.tmp arch/arm/dts/.myimx8mek314-8mq.dtb.pre.tmp ; ./scripts/dtc/dtc -O dtb -o arch/arm/dts/myimx8mek314-8mq.dtb -b 0 -i arch/arm/dts/  -Wno-unit_address_vs_reg -Wno-simple_bus_reg -Wno-unit_address_format -Wno-pci_bridge -Wno-pci_device_bus_num -Wno-pci_device_reg  -d arch/arm/dts/.myimx8mek314-8mq.dtb.d.dtc.tmp arch/arm/dts/.myimx8mek314-8mq.dtb.dts.tmp ; cat arch/arm/dts/.myimx8mek314-8mq.dtb.d.pre.tmp arch/arm/dts/.myimx8mek314-8mq.dtb.d.dtc.tmp > arch/arm/dts/.myimx8mek314-8mq.dtb.d
  mkdir -p arch/arm/dts/ ; (cat arch/arm/dts/myimx8mevk-8mq.dts; ) > arch/arm/dts/.myimx8mevk-8mq.dtb.pre.tmp; /home/h/my-work/03_toolchain/gcc-linaro-7.3.1-2018.05-x86_64_aarch64-linux-gnu/bin/aarch64-linux-gnu-gcc -E -Wp,-MD,arch/arm/dts/.myimx8mevk-8mq.dtb.d.pre.tmp -nostdinc -I./arch/arm/dts -I./arch/arm/dts/include -Iinclude -I./include -I./arch/arm/include -include ./include/linux/kconfig.h -D__ASSEMBLY__ -undef -D__DTS__ -x assembler-with-cpp -o arch/arm/dts/.myimx8mevk-8mq.dtb.dts.tmp arch/arm/dts/.myimx8mevk-8mq.dtb.pre.tmp ; ./scripts/dtc/dtc -O dtb -o arch/arm/dts/myimx8mevk-8mq.dtb -b 0 -i arch/arm/dts/  -Wno-unit_address_vs_reg -Wno-simple_bus_reg -Wno-unit_address_format -Wno-pci_bridge -Wno-pci_device_bus_num -Wno-pci_device_reg  -d arch/arm/dts/.myimx8mevk-8mq.dtb.d.dtc.tmp arch/arm/dts/.myimx8mevk-8mq.dtb.dts.tmp ; cat arch/arm/dts/.myimx8mevk-8mq.dtb.d.pre.tmp arch/arm/dts/.myimx8mevk-8mq.dtb.d.dtc.tmp > arch/arm/dts/.myimx8mevk-8mq.dtb.d
  mkdir -p arch/arm/dts/ ; (cat arch/arm/dts/myimx8mek300-8mq.dts; ) > arch/arm/dts/.myimx8mek300-8mq.dtb.pre.tmp; /home/h/my-work/03_toolchain/gcc-linaro-7.3.1-2018.05-x86_64_aarch64-linux-gnu/bin/aarch64-linux-gnu-gcc -E -Wp,-MD,arch/arm/dts/.myimx8mek300-8mq.dtb.d.pre.tmp -nostdinc -I./arch/arm/dts -I./arch/arm/dts/include -Iinclude -I./include -I./arch/arm/include -include ./include/linux/kconfig.h -D__ASSEMBLY__ -undef -D__DTS__ -x assembler-with-cpp -o arch/arm/dts/.myimx8mek300-8mq.dtb.dts.tmp arch/arm/dts/.myimx8mek300-8mq.dtb.pre.tmp ; ./scripts/dtc/dtc -O dtb -o arch/arm/dts/myimx8mek300-8mq.dtb -b 0 -i arch/arm/dts/  -Wno-unit_address_vs_reg -Wno-simple_bus_reg -Wno-unit_address_format -Wno-pci_bridge -Wno-pci_device_bus_num -Wno-pci_device_reg  -d arch/arm/dts/.myimx8mek300-8mq.dtb.d.dtc.tmp arch/arm/dts/.myimx8mek300-8mq.dtb.dts.tmp ; cat arch/arm/dts/.myimx8mek300-8mq.dtb.d.pre.tmp arch/arm/dts/.myimx8mek300-8mq.dtb.d.dtc.tmp > arch/arm/dts/.myimx8mek300-8mq.dtb.d
  mkdir -p arch/arm/dts/ ; (cat arch/arm/dts/myimx8mmek240-8mm.dts; ) > arch/arm/dts/.myimx8mmek240-8mm.dtb.pre.tmp; /home/h/my-work/03_toolchain/gcc-linaro-7.3.1-2018.05-x86_64_aarch64-linux-gnu/bin/aarch64-linux-gnu-gcc -E -Wp,-MD,arch/arm/dts/.myimx8mmek240-8mm.dtb.d.pre.tmp -nostdinc -I./arch/arm/dts -I./arch/arm/dts/include -Iinclude -I./include -I./arch/arm/include -include ./include/linux/kconfig.h -D__ASSEMBLY__ -undef -D__DTS__ -x assembler-with-cpp -o arch/arm/dts/.myimx8mmek240-8mm.dtb.dts.tmp arch/arm/dts/.myimx8mmek240-8mm.dtb.pre.tmp ; ./scripts/dtc/dtc -O dtb -o arch/arm/dts/myimx8mmek240-8mm.dtb -b 0 -i arch/arm/dts/  -Wno-unit_address_vs_reg -Wno-simple_bus_reg -Wno-unit_address_format -Wno-pci_bridge -Wno-pci_device_bus_num -Wno-pci_device_reg  -d arch/arm/dts/.myimx8mmek240-8mm.dtb.d.dtc.tmp arch/arm/dts/.myimx8mmek240-8mm.dtb.dts.tmp ; cat arch/arm/dts/.myimx8mmek240-8mm.dtb.d.pre.tmp arch/arm/dts/.myimx8mmek240-8mm.dtb.d.dtc.tmp > arch/arm/dts/.myimx8mmek240-8mm.dtb.d
  mkdir -p arch/arm/dts/ ; (cat arch/arm/dts/fsl-imx8mq-evk.dts; echo '#include "fsl-imx8mq-evk-u-boot.dtsi"') > arch/arm/dts/.fsl-imx8mq-evk.dtb.pre.tmp; /home/h/my-work/03_toolchain/gcc-linaro-7.3.1-2018.05-x86_64_aarch64-linux-gnu/bin/aarch64-linux-gnu-gcc -E -Wp,-MD,arch/arm/dts/.fsl-imx8mq-evk.dtb.d.pre.tmp -nostdinc -I./arch/arm/dts -I./arch/arm/dts/include -Iinclude -I./include -I./arch/arm/include -include ./include/linux/kconfig.h -D__ASSEMBLY__ -undef -D__DTS__ -x assembler-with-cpp -o arch/arm/dts/.fsl-imx8mq-evk.dtb.dts.tmp arch/arm/dts/.fsl-imx8mq-evk.dtb.pre.tmp ; ./scripts/dtc/dtc -O dtb -o arch/arm/dts/fsl-imx8mq-evk.dtb -b 0 -i arch/arm/dts/  -Wno-unit_address_vs_reg -Wno-simple_bus_reg -Wno-unit_address_format -Wno-pci_bridge -Wno-pci_device_bus_num -Wno-pci_device_reg  -d arch/arm/dts/.fsl-imx8mq-evk.dtb.d.dtc.tmp arch/arm/dts/.fsl-imx8mq-evk.dtb.dts.tmp ; cat arch/arm/dts/.fsl-imx8mq-evk.dtb.d.pre.tmp arch/arm/dts/.fsl-imx8mq-evk.dtb.d.dtc.tmp > arch/arm/dts/.fsl-imx8mq-evk.dtb.d
  mkdir -p arch/arm/dts/ ; (cat arch/arm/dts/fsl-imx8mq-ddr3l-arm2.dts; echo '#include "fsl-imx8mq-ddr3l-arm2-u-boot.dtsi"') > arch/arm/dts/.fsl-imx8mq-ddr3l-arm2.dtb.pre.tmp; /home/h/my-work/03_toolchain/gcc-linaro-7.3.1-2018.05-x86_64_aarch64-linux-gnu/bin/aarch64-linux-gnu-gcc -E -Wp,-MD,arch/arm/dts/.fsl-imx8mq-ddr3l-arm2.dtb.d.pre.tmp -nostdinc -I./arch/arm/dts -I./arch/arm/dts/include -Iinclude -I./include -I./arch/arm/include -include ./include/linux/kconfig.h -D__ASSEMBLY__ -undef -D__DTS__ -x assembler-with-cpp -o arch/arm/dts/.fsl-imx8mq-ddr3l-arm2.dtb.dts.tmp arch/arm/dts/.fsl-imx8mq-ddr3l-arm2.dtb.pre.tmp ; ./scripts/dtc/dtc -O dtb -o arch/arm/dts/fsl-imx8mq-ddr3l-arm2.dtb -b 0 -i arch/arm/dts/  -Wno-unit_address_vs_reg -Wno-simple_bus_reg -Wno-unit_address_format -Wno-pci_bridge -Wno-pci_device_bus_num -Wno-pci_device_reg  -d arch/arm/dts/.fsl-imx8mq-ddr3l-arm2.dtb.d.dtc.tmp arch/arm/dts/.fsl-imx8mq-ddr3l-arm2.dtb.dts.tmp ; cat arch/arm/dts/.fsl-imx8mq-ddr3l-arm2.dtb.d.pre.tmp arch/arm/dts/.fsl-imx8mq-ddr3l-arm2.dtb.d.dtc.tmp > arch/arm/dts/.fsl-imx8mq-ddr3l-arm2.dtb.d
  mkdir -p arch/arm/dts/ ; (cat arch/arm/dts/fsl-imx8mq-ddr4-arm2.dts; echo '#include "fsl-imx8mq-ddr4-arm2-u-boot.dtsi"') > arch/arm/dts/.fsl-imx8mq-ddr4-arm2.dtb.pre.tmp; /home/h/my-work/03_toolchain/gcc-linaro-7.3.1-2018.05-x86_64_aarch64-linux-gnu/bin/aarch64-linux-gnu-gcc -E -Wp,-MD,arch/arm/dts/.fsl-imx8mq-ddr4-arm2.dtb.d.pre.tmp -nostdinc -I./arch/arm/dts -I./arch/arm/dts/include -Iinclude -I./include -I./arch/arm/include -include ./include/linux/kconfig.h -D__ASSEMBLY__ -undef -D__DTS__ -x assembler-with-cpp -o arch/arm/dts/.fsl-imx8mq-ddr4-arm2.dtb.dts.tmp arch/arm/dts/.fsl-imx8mq-ddr4-arm2.dtb.pre.tmp ; ./scripts/dtc/dtc -O dtb -o arch/arm/dts/fsl-imx8mq-ddr4-arm2.dtb -b 0 -i arch/arm/dts/  -Wno-unit_address_vs_reg -Wno-simple_bus_reg -Wno-unit_address_format -Wno-pci_bridge -Wno-pci_device_bus_num -Wno-pci_device_reg  -d arch/arm/dts/.fsl-imx8mq-ddr4-arm2.dtb.d.dtc.tmp arch/arm/dts/.fsl-imx8mq-ddr4-arm2.dtb.dts.tmp ; cat arch/arm/dts/.fsl-imx8mq-ddr4-arm2.dtb.d.pre.tmp arch/arm/dts/.fsl-imx8mq-ddr4-arm2.dtb.d.dtc.tmp > arch/arm/dts/.fsl-imx8mq-ddr4-arm2.dtb.d
  mkdir -p arch/arm/dts/ ; (cat arch/arm/dts/fsl-imx8mq-phanbell.dts; echo '#include "fsl-imx8mq-phanbell-u-boot.dtsi"') > arch/arm/dts/.fsl-imx8mq-phanbell.dtb.pre.tmp; /home/h/my-work/03_toolchain/gcc-linaro-7.3.1-2018.05-x86_64_aarch64-linux-gnu/bin/aarch64-linux-gnu-gcc -E -Wp,-MD,arch/arm/dts/.fsl-imx8mq-phanbell.dtb.d.pre.tmp -nostdinc -I./arch/arm/dts -I./arch/arm/dts/include -Iinclude -I./include -I./arch/arm/include -include ./include/linux/kconfig.h -D__ASSEMBLY__ -undef -D__DTS__ -x assembler-with-cpp -o arch/arm/dts/.fsl-imx8mq-phanbell.dtb.dts.tmp arch/arm/dts/.fsl-imx8mq-phanbell.dtb.pre.tmp ; ./scripts/dtc/dtc -O dtb -o arch/arm/dts/fsl-imx8mq-phanbell.dtb -b 0 -i arch/arm/dts/  -Wno-unit_address_vs_reg -Wno-simple_bus_reg -Wno-unit_address_format -Wno-pci_bridge -Wno-pci_device_bus_num -Wno-pci_device_reg  -d arch/arm/dts/.fsl-imx8mq-phanbell.dtb.d.dtc.tmp arch/arm/dts/.fsl-imx8mq-phanbell.dtb.dts.tmp ; cat arch/arm/dts/.fsl-imx8mq-phanbell.dtb.d.pre.tmp arch/arm/dts/.fsl-imx8mq-phanbell.dtb.d.dtc.tmp > arch/arm/dts/.fsl-imx8mq-phanbell.dtb.d
  mkdir -p arch/arm/dts/ ; (cat arch/arm/dts/fsl-imx8mm-ddr3l-val.dts; ) > arch/arm/dts/.fsl-imx8mm-ddr3l-val.dtb.pre.tmp; /home/h/my-work/03_toolchain/gcc-linaro-7.3.1-2018.05-x86_64_aarch64-linux-gnu/bin/aarch64-linux-gnu-gcc -E -Wp,-MD,arch/arm/dts/.fsl-imx8mm-ddr3l-val.dtb.d.pre.tmp -nostdinc -I./arch/arm/dts -I./arch/arm/dts/include -Iinclude -I./include -I./arch/arm/include -include ./include/linux/kconfig.h -D__ASSEMBLY__ -undef -D__DTS__ -x assembler-with-cpp -o arch/arm/dts/.fsl-imx8mm-ddr3l-val.dtb.dts.tmp arch/arm/dts/.fsl-imx8mm-ddr3l-val.dtb.pre.tmp ; ./scripts/dtc/dtc -O dtb -o arch/arm/dts/fsl-imx8mm-ddr3l-val.dtb -b 0 -i arch/arm/dts/  -Wno-unit_address_vs_reg -Wno-simple_bus_reg -Wno-unit_address_format -Wno-pci_bridge -Wno-pci_device_bus_num -Wno-pci_device_reg  -d arch/arm/dts/.fsl-imx8mm-ddr3l-val.dtb.d.dtc.tmp arch/arm/dts/.fsl-imx8mm-ddr3l-val.dtb.dts.tmp ; cat arch/arm/dts/.fsl-imx8mm-ddr3l-val.dtb.d.pre.tmp arch/arm/dts/.fsl-imx8mm-ddr3l-val.dtb.d.dtc.tmp > arch/arm/dts/.fsl-imx8mm-ddr3l-val.dtb.d
  mkdir -p arch/arm/dts/ ; (cat arch/arm/dts/fsl-imx8mm-ddr4-evk.dts; ) > arch/arm/dts/.fsl-imx8mm-ddr4-evk.dtb.pre.tmp; /home/h/my-work/03_toolchain/gcc-linaro-7.3.1-2018.05-x86_64_aarch64-linux-gnu/bin/aarch64-linux-gnu-gcc -E -Wp,-MD,arch/arm/dts/.fsl-imx8mm-ddr4-evk.dtb.d.pre.tmp -nostdinc -I./arch/arm/dts -I./arch/arm/dts/include -Iinclude -I./include -I./arch/arm/include -include ./include/linux/kconfig.h -D__ASSEMBLY__ -undef -D__DTS__ -x assembler-with-cpp -o arch/arm/dts/.fsl-imx8mm-ddr4-evk.dtb.dts.tmp arch/arm/dts/.fsl-imx8mm-ddr4-evk.dtb.pre.tmp ; ./scripts/dtc/dtc -O dtb -o arch/arm/dts/fsl-imx8mm-ddr4-evk.dtb -b 0 -i arch/arm/dts/  -Wno-unit_address_vs_reg -Wno-simple_bus_reg -Wno-unit_address_format -Wno-pci_bridge -Wno-pci_device_bus_num -Wno-pci_device_reg  -d arch/arm/dts/.fsl-imx8mm-ddr4-evk.dtb.d.dtc.tmp arch/arm/dts/.fsl-imx8mm-ddr4-evk.dtb.dts.tmp ; cat arch/arm/dts/.fsl-imx8mm-ddr4-evk.dtb.d.pre.tmp arch/arm/dts/.fsl-imx8mm-ddr4-evk.dtb.d.dtc.tmp > arch/arm/dts/.fsl-imx8mm-ddr4-evk.dtb.d
  mkdir -p arch/arm/dts/ ; (cat arch/arm/dts/fsl-imx8mm-ddr4-val.dts; ) > arch/arm/dts/.fsl-imx8mm-ddr4-val.dtb.pre.tmp; /home/h/my-work/03_toolchain/gcc-linaro-7.3.1-2018.05-x86_64_aarch64-linux-gnu/bin/aarch64-linux-gnu-gcc -E -Wp,-MD,arch/arm/dts/.fsl-imx8mm-ddr4-val.dtb.d.pre.tmp -nostdinc -I./arch/arm/dts -I./arch/arm/dts/include -Iinclude -I./include -I./arch/arm/include -include ./include/linux/kconfig.h -D__ASSEMBLY__ -undef -D__DTS__ -x assembler-with-cpp -o arch/arm/dts/.fsl-imx8mm-ddr4-val.dtb.dts.tmp arch/arm/dts/.fsl-imx8mm-ddr4-val.dtb.pre.tmp ; ./scripts/dtc/dtc -O dtb -o arch/arm/dts/fsl-imx8mm-ddr4-val.dtb -b 0 -i arch/arm/dts/  -Wno-unit_address_vs_reg -Wno-simple_bus_reg -Wno-unit_address_format -Wno-pci_bridge -Wno-pci_device_bus_num -Wno-pci_device_reg  -d arch/arm/dts/.fsl-imx8mm-ddr4-val.dtb.d.dtc.tmp arch/arm/dts/.fsl-imx8mm-ddr4-val.dtb.dts.tmp ; cat arch/arm/dts/.fsl-imx8mm-ddr4-val.dtb.d.pre.tmp arch/arm/dts/.fsl-imx8mm-ddr4-val.dtb.d.dtc.tmp > arch/arm/dts/.fsl-imx8mm-ddr4-val.dtb.d
  mkdir -p arch/arm/dts/ ; (cat arch/arm/dts/fsl-imx8mm-evk.dts; ) > arch/arm/dts/.fsl-imx8mm-evk.dtb.pre.tmp; /home/h/my-work/03_toolchain/gcc-linaro-7.3.1-2018.05-x86_64_aarch64-linux-gnu/bin/aarch64-linux-gnu-gcc -E -Wp,-MD,arch/arm/dts/.fsl-imx8mm-evk.dtb.d.pre.tmp -nostdinc -I./arch/arm/dts -I./arch/arm/dts/include -Iinclude -I./include -I./arch/arm/include -include ./include/linux/kconfig.h -D__ASSEMBLY__ -undef -D__DTS__ -x assembler-with-cpp -o arch/arm/dts/.fsl-imx8mm-evk.dtb.dts.tmp arch/arm/dts/.fsl-imx8mm-evk.dtb.pre.tmp ; ./scripts/dtc/dtc -O dtb -o arch/arm/dts/fsl-imx8mm-evk.dtb -b 0 -i arch/arm/dts/  -Wno-unit_address_vs_reg -Wno-simple_bus_reg -Wno-unit_address_format -Wno-pci_bridge -Wno-pci_device_bus_num -Wno-pci_device_reg  -d arch/arm/dts/.fsl-imx8mm-evk.dtb.d.dtc.tmp arch/arm/dts/.fsl-imx8mm-evk.dtb.dts.tmp ; cat arch/arm/dts/.fsl-imx8mm-evk.dtb.d.pre.tmp arch/arm/dts/.fsl-imx8mm-evk.dtb.d.dtc.tmp > arch/arm/dts/.fsl-imx8mm-evk.dtb.d

2. arch/arm/dts/myimx8mmek240-8mm.dts

文件存在即可。

17.1.2 $(DTB)规则

make -f $(srctree)/scripts/Makefile.build obj=arch/arm/dts arch/arm/dts/myimx8mmek240-8mm.dtb

arch/arm/dts/myimx8mmek240-8mm.dtb的实际编译位置在17.1.1-1中。

# <<<<<<<<<scripts/Makefile.lib >>>>>>>>>
# Shipped files
# ===========================================================================

quiet_cmd_shipped = SHIPPED $@
cmd_shipped = cat $< > $@   //$<:第一个依赖对象arch/arm/dts/myimx8mmek240-8mm.dtb

# <<<<<<<<<dts/Makefile >>>>>>>>>
$(obj)/dt.dtb: $(DTB) FORCE     //关注dts/dt.dtb
    $(call if_changed,shipped)

没什么好讲的,具体编译过程如下:

  cat arch/arm/dts/myimx8mmek240-8mm.dtb > dts/dt.dtb


# <<<<<<<<<scripts/Makefile.lib >>>>>>>>>
# fdtgrep
# ---------------------------------------------------------------------------
# Pass the original device tree file through fdtgrep twice. The first pass
# removes any unwanted nodes (i.e. those which don't have the
# 'u-boot,dm-pre-reloc' property and thus are not needed by SPL. The second
# pass removes various unused properties from the remaining nodes.
# The output is typically a much smaller device tree file.
ifeq ($(CONFIG_TPL_BUILD),y)
fdtgrep_props := -b u-boot,dm-pre-reloc -b u-boot,dm-tpl
else
fdtgrep_props := -b u-boot,dm-pre-reloc -b u-boot,dm-spl
endif
quiet_cmd_fdtgrep = FDTGREP $@
      cmd_fdtgrep = $(objtree)/tools/fdtgrep $(fdtgrep_props) -RT $< \
        -n /chosen -n /config -O dtb | \
    $(objtree)/tools/fdtgrep -r -O dtb - -o $@ \
        $(addprefix -P ,$(subst $\",,$(CONFIG_OF_SPL_REMOVE_PROPS)))

$(obj)/dt-spl.dtb: $(DTB) $(objtree)/tools/fdtgrep FORCE //关注
    $(call if_changed,fdtgrep)

将原始设备树文件通过fdtgrep两次处理:

  • 第一个过程:删除任何不需要的节点(比如去掉不含“u-boot,dm pre reloc”属性的节点,因为SPL不需要这些节点)。
  • 第二个过程:从其余节点中删除各种未使用的属性。

输出通常是一个小得多的设备树文件。

没什么好讲的,具体编译过程如下:

 ./tools/fdtgrep -b u-boot,dm-pre-reloc -b u-boot,dm-spl -RT arch/arm/dts/myimx8mmek240-8mm.dtb -n /chosen -n /config -O dtb | ./tools/fdtgrep -r -O dtb - -o dts/dt-spl.dtb

参数解释如下

  • -b:properties in the node;
  • -R :Include the root node and all properties;
  • -T :Add aliases node to output
  • -n :要保留的节点名;
  • -O :Output formats;
  • -r :Remove unused strings;
  • -o:Output filename;

最终生成的dts/dt-spl.dtb对应的dts内容如下:

18. u-boot-dtb.bin

# <<<<<<<<<顶层Makefile>>>>>>>>>
quiet_cmd_cat = CAT     $@
cmd_cat = cat $(filter-out $(PHONY), $^) > $@

......

u-boot-dtb.bin: u-boot-nodtb.bin dts/dt.dtb FORCE
    $(call if_changed,cat)

没什么好讲的,就是把u-boot-nodtb.bin和dts/dt.dtb打包成u-boot-dtb.bin。具体编译过程如下:

cat u-boot-nodtb.bin dts/dt.dtb > u-boot-dtb.bin

19. u-boot.bin

# <<<<<<<<<顶层Makefile>>>>>>>>>
quiet_cmd_copy = COPY    $@
      cmd_copy = cp $< $@

......

u-boot.bin: u-boot-dtb.bin FORCE
    $(call if_changed,copy)

没什么好讲的,就是把u-boot-dtb.bin 重命名为u-boot.bin。具体编译过程如下:

cp u-boot-dtb.bin u-boot.bin

20. u-boot.img/u-boot-dtb.img

# <<<<<<<<<顶层Makefile>>>>>>>>>
MKIMAGEFLAGS_u-boot.img = -f auto -A $(ARCH) -T firmware -C none -O u-boot \
    -a $(CONFIG_SYS_TEXT_BASE) -e $(CONFIG_SYS_UBOOT_START) \
    -n "U-Boot $(UBOOTRELEASE) for $(BOARD) board" -E \
    $(patsubst %,-b arch/$(ARCH)/dts/%.dtb,$(subst ",,$(CONFIG_OF_LIST)))

MKIMAGEFLAGS_u-boot-dtb.img = $(MKIMAGEFLAGS_u-boot.img)

quiet_cmd_mkimage = MKIMAGE $@
cmd_mkimage = $(objtree)/tools/mkimage $(MKIMAGEFLAGS_$(@F)) -d $< $@ \ //$(@F)为
    $(if $(KBUILD_VERBOSE:1=), >$(MKIMAGEOUTPUT))

u-boot-dtb.img u-boot.img u-boot.kwb u-boot.pbl u-boot-ivt.img: \            //CONFIG_SPL_LOAD_FIT =1
        $(if $(CONFIG_SPL_LOAD_FIT),u-boot-nodtb.bin dts/dt.dtb,u-boot.bin) FORCE
    $(call if_changed,mkimage)

很简单,就是调用mkimage 工具制作带有mkimage头的U-Boot映像。注意u-boot.img和u-boot-dtb.img内容相同。

用到的mkimage参数解释如下:

-A ==> set architecture to 'arch'

-O ==> set operating system to 'os'

-T ==> set image type to 'type'

-C ==> set compression type 'comp'

-a ==> set load address to 'addr' (hex)"

-e ==> set entry point to 'ep' (hex)

-n ==> set image name to 'name'

-d ==> use image data from 'datafile'

-b ==> dtb

-E => place data outside of the FIT structure

具体编译过程如下:

./tools/mkimage -f auto -A arm -T firmware -C none -O u-boot -a 0x40200000 -e 0 -n "U-Boot 2018.03"" for myimx8mm board" -E -b arch/arm/dts/myimx8mmek240-8mm.dtb -d u-boot-nodtb.bin u-boot.img

./tools/mkimage -f auto -A arm -T firmware -C none -O u-boot -a 0x40200000 -e 0 -n "U-Boot 2018.03"" for myimx8mm board" -E -b arch/arm/dts/myimx8mmek240-8mm.dtb -d u-boot-nodtb.bin u-boot-dtb.img

21. u-boot.dtb

# <<<<<<<<<顶层Makefile>>>>>>>>>
quiet_cmd_copy = COPY    $@
      cmd_copy = cp $< $@

u-boot.dtb: dts/dt.dtb
    $(call cmd,copy)

没什么好讲的,就是把dts/dt.dtb 重命名为u-boot.dtb。具体编译过程如下:

cp dts/dt.dtb u-boot.dtb

22. binary_size_check

# <<<<<<<<<顶层Makefile>>>>>>>>>
binary_size_check: u-boot-nodtb.bin FORCE
    @file_size=$(shell wc -c u-boot-nodtb.bin | awk '{print $$1}') ; \ //获取文件大小
    map_size=$(shell cat u-boot.map | \
        awk '/_image_copy_start/ {start = $$1} /_image_binary_end/ {end = $$1} END {if (start != "" && end != "") print "ibase=16; " toupper(end) " - " toupper(start)}' \
        | sed 's/0X//g' \
        | bc); \
    if [ "" != "$$map_size" ]; then \
        if test $$map_size -ne $$file_size; then \
            echo "u-boot.map shows a binary size of $$map_size" >&2 ; \
            echo "  but u-boot-nodtb.bin shows $$file_size" >&2 ; \
            exit 1; \
        fi \
    fi
  • shell wc -c : wc命令的功能为统计指定文件中的字节数、字数、行数, 并将统计结果显示输出。- c 统计字节数;
  • $$1 : makefile中展开为$1,shell中$1表示第一个参数;
  • sed 's/0X//g' :把每一行的'0X'替换为空,即去掉地址的0X前缀;
  • toupper :转换为大写;
  • ibase=16 :设置输入为16进制,默认值为10;
  • sed 's/0X//g':'0X'替换为空;
  • bc :能够对计算公式的语法进行解释并返回出结果
  • test -ne :不等于则为真

上述命令:就是

  • 把 u-boot.map中的_image_copy_start去掉0X赋值给start,_image_binary_end地址值去掉0X赋值给end;
  • 如果start 不为空且end 不为空,则计算end-start的差值,并赋值给map_size,这时未指定输出格式,默认为10进制数据。
  • 然后把十六进制的0X去掉;
  • 输出10进制数值;
  • 判断map_size是否为空,如果不为空。则继续判断map_size是否等于file_size(u-boot-nodtb.bin的大小);

23. u-boot.srec

# <<<<<<<<<顶层Makefile>>>>>>>>>
OBJCOPYFLAGS_u-boot.srec := -O srec

# Normally we fill empty space with 0xff
quiet_cmd_objcopy = OBJCOPY $@
cmd_objcopy = $(OBJCOPY) --gap-fill=0xff $(OBJCOPYFLAGS) \
    $(OBJCOPYFLAGS_$(@F)) $< $@
......

u-boot.hex u-boot.srec: u-boot FORCE
    $(call if_changed,objcopy)

objcopy的功能:将目标文件的一部分或者全部内容拷贝到另外一个目标文件中,或者实现目标文件的格式转换。

  • j sectionname , --only-section=sectionname : 只将由 sectionname 指定的 section 拷贝到输出文件,可以多次指定,并且注意如果使用不当会导致输出文件不可用。

    -O bfdname :--output-target= bfdname 使用指定的格式来写输出文件(即目标文件),bfdname是BFD库中描述的标准格式名。

具体编译过程如下:

/home/h/my-work/03_toolchain/gcc-linaro-7.3.1-2018.05-x86_64_aarch64-linux-gnu/bin/aarch64-linux-gnu-objcopy --gap-fill=0xff  -j .text -j .secure_text -j .secure_data -j .rodata -j .data -j .u_boot_list -j .rela.dyn -j .got -j .got.plt -j .binman_sym_table -j .dtb.init.rodata -j .efi_runtime -j .efi_runtime_rel -O srec u-boot u-boot.srec

24. u-boot.sym

# <<<<<<<<<顶层Makefile>>>>>>>>>
quiet_cmd_sym ?= SYM     $@
      cmd_sym ?= $(OBJDUMP) -t $< > $@

......

u-boot.sym: u-boot FORCE
    $(call if_changed,sym)

objdump的功能:是Linux下的反汇编目标文件或者可执行文件的命令:

-t /--syms :显示文件的符号表入口。类似于nm -s提供的信息 。

具体编译过程如下:

/home/h/my-work/03_toolchain/gcc-linaro-7.3.1-2018.05-x86_64_aarch64-linux-gnu/bin/aarch64-linux-gnu-objdump -t u-boot > u-boot.sym

25. System.map

# <<<<<<<<<顶层Makefile>>>>>>>>>
SYSTEM_MAP = \
        $(NM) $1 | \
        grep -v '\(compiled\)\|\(\.o$$\)\|\( [aUw] \)\|\(\.\.ng$$\)\|\(LASH[RL]DI\)' | \
        LC_ALL=C sort
System.map:    u-boot
        @$(call SYSTEM_MAP,$<) > $@

具体编译过程如下:

/home/h/my-work/03_toolchain/gcc-linaro-7.3.1-2018.05-x86_64_aarch64-linux-gnu/bin/aarch64-linux-gnu-nm u-boot | grep -v '\(compiled\)\|\(\.o$\)\|\( [aUw] \)\|\(\.\.ng$\)\|\(LASH[RL]DI\)' | LC_ALL=C sort > System.map
  • grep -v : 是反向查找的意思,比如 grep -v grep 就是查找不含有 grep 字段的行 。
  • ' '中的内容 :引号中的 \ 是转义的意思,即不把 / 后面的当作命令信息解释。
  • LC_ALL=C : 去除所有本地化的设置,让命令能正确执行。"C"是系统默认的locale,"POSIX"是"C"的别名
  • sort : 排序

也就是将nm命令查看u-boot的输出信息经过过滤排序后输出到System.map。

System.map表示的是地址标号到该标号表示的地址的一个映射关系。System.map每一行的格式都是“addr type name”,addr是标号对应的地址值,name是标号名,type表示标号的类型。

U-Boot的编译和运行并不一定要生成System.map,这个文件主要是提供给用户或外部程序调试时使用的。

.

26. 关于SPL镜像

由于篇幅有限这里先不讲,后面单独讲。

27. 总结

成功编译之后,就会在 U-Boot 源码的根目录下产生多个可执行二进制文件以及编译过程文件,这些文件都是 u-boot.xxx 的命名方式,对应目录下的.xxx.cmd 这些文件都是由编译时的具体指令(if_changed函数中生成$(dot-target).cmd)。

  • -- u-boot:ELF 格式的 U-Boot 镜像文件,后续的文件都是由它产生的。具体编译过程参见u-boot.cmd ;
  • -- dts/dt.dtb:设备树 (来自于 arch/arm/dts/myimx8mmek240-8mm.dtb 重命名,具体编译过程参见.myimx8mmek240-8mm.dtb.cmd);
  • -- u-boot.dtb:dts/dt.dtb的重命名;
  • -- u-boot-nodtb.bin: 使用编译工具链的 objcopy 工具从 u-boot 这个文件中提取来的,它只包含可执行的二进制代码。就是把 u-boot 这个文件中对于执行不需要的节区删除后剩余的仅执行需要的部分。具体编译过程参见.u-boot-nodtb.bin.cmd;
  • -- u-boot-dtb.bin:在 u-boot-nodtb.bin 尾部拼接上设备树后形成的文件。具体编译过程参见 .u-boot-dtb.bin.cmd;
  • -- u-boot.bin:编译出来的二进制格式的uboot可执行镜像文件 。在我使用的单板等价于 u-boot-dtb.bin。具体编译过程参见 .u-boot-dtb.bin.cmd;
  • -- u-boot.cfg:uboot的另外一种配置文件 .
  • -- u-boot.img/u-boot-dtb.img :调用mkimage 工具制作带有mkimage头的U-Boot映像 ,输入是u-boot-nodtb.bin。具体编译过程参见 .u-boot.img.cmd 和 .u-boot-dtb.img.cmd;
  • -- u-boot.lds:链接脚本 。具体编译过程参见 .u-boot.lds.cmd;
  • -- u-boot.map:uboot映射文件,可查看某个函数被链接到哪个地址上了 。具体编译过程参见u-boot.cmd ;
  • -- u-boot.srec:S-Record格式的镜像文件 。具体编译过程参见 .u-boot.srec.cmd;
  • -- u-boot.sym:uboot符号表文件 。具体编译过程参见 .u-boot.sym.cmd

28. 参考

[1] '-E' 只执行到预编译,只涉及到宏替换、头文件展开 、注释去掉(在预处理阶段结束后停止'-E');

[2] '-x' 为输入文件显式指定语言(而不是让编译器根据文件名后缀选择默认语言)(显式指定语言'-x');

[3] '-P' 删除无用的信息(预处理器控制选项 -P);

[4] 利用gcc -E -P 进行宏替换 宏展开 预处理文件;

[5] makefile中$$的使用