官方文档
https://wiki.t-firefly.com/zh_CN/ROC-RK3588S-PC/linux_compile_debian.html

整编过程中遇到的问题

  • 1.网上下载依赖库一直没有反应
    在源码的根目录下,会有一个br.log文件,记录着详细的编译异常日志,包括下载依赖库。

了解一下buildroot编译框架,发现下载的包都在buildroot/dl目录下,新建一个文件夹名字为库的名字,观看已经下载下来的包的格式,到github上找到这个库然后下载下来放到这个以库同名的文件夹下。

直接把github开头的链接进行下载即可

  • 2.dl下的库已经手动下载替换了,build时还是会去下载然后卡在那里。

    把buildroot/package下的这个文件夹alsa-ucm-conf下的mk文件删除掉(注意不要删除整个文件夹,否则后面build的时候会报找不到这个库的Config.in文件导致编译失败),重新build则会去下载别的库。

整编脚本解析

  • envsetup.sh
    作用:为buildroot的Makefile选择一个目标config
function main()
{
    #查找buildroot/configs目录下所有以rockchip_的开头的文件名,并将文件名最后的_defconfig字符串去掉。
    RK_DEFCONFIG_ARRAY=(
        $(cd ${BUILDROOT_DIR}/configs/; ls rockchip_* | \
            sed "s/_defconfig$//" | grep "$1" | sort)
    )

    unset RK_BUILD_CONFIG
    RK_DEFCONFIG_ARRAY_LEN=${#RK_DEFCONFIG_ARRAY[@]}

    case $RK_DEFCONFIG_ARRAY_LEN in
        0)
            echo No available configs${1:+" for: $1"}
            ;;  
        1)
            RK_BUILD_CONFIG=${RK_DEFCONFIG_ARRAY[0]}
            ;;
        *)
            #如果在执行envsetup.sh时指定板子的配置模板,就不选择。
            if [ "$1" = ${RK_DEFCONFIG_ARRAY[0]} ]; then
                # Prefer exact-match
                RK_BUILD_CONFIG=$1
            else
                choose_board
            fi
            ;;
    esac

    [ -n "$RK_BUILD_CONFIG" ] || return

    #这里的.BoardConfig.mk是一个链接文件,指向lunch指令选择的板子配置文件。
    #将环境变量加入shell环境
    source ${TOP_DIR}/device/rockchip/.BoardConfig.mk

    lunch_rockchip

    # Set alias
    alias croot="cd ${TOP_DIR}"
    alias broot="cd ${BUILDROOT_DIR}"
    alias bpkg="cd ${BUILDROOT_DIR}/package"
    alias bout="cd ${TARGET_OUTPUT_DIR}"
}

/buildroot/configs

function choose_board()
{
    echo
    echo "You're building on Linux"
    echo "Lunch menu...pick a combo:"
    echo ""

    echo "0. non-rockchip boards"
    echo ${RK_DEFCONFIG_ARRAY[@]} | xargs -n 1 | sed "=" | sed "N;s/\n/. /"

    local INDEX
    while true; do
        read -p "Which would you like? [0]: " INDEX
        #index如果没有输入,默认为0,再减去1.也就是-1为index的默认值
        INDEX=$((${INDEX:-0} - 1))

        #没有选择
        if [ "$INDEX" -eq -1 ]; then
            echo "Lunching for non-rockchip boards..."
            unset TARGET_OUTPUT_DIR
            unset RK_BUILD_CONFIG
            break;
        fi

        if echo $INDEX | grep -vq [^0-9]; then
            RK_BUILD_CONFIG="${RK_DEFCONFIG_ARRAY[$INDEX]}"
            [ -n "$RK_BUILD_CONFIG" ] && break
        fi

        echo
        echo "Choice not available. Please try again."
        echo
    done
}
function lunch_rockchip()
{
    TARGET_DIR_NAME="$RK_BUILD_CONFIG"
    export TARGET_OUTPUT_DIR="$BUILDROOT_OUTPUT_DIR/$TARGET_DIR_NAME"

    mkdir -p $TARGET_OUTPUT_DIR || return

    echo "==========================================="
    echo
    #打印_后字符串
    echo "#TARGET_BOARD=`echo $RK_BUILD_CONFIG | cut -d '_' -f 2`"
    echo "#OUTPUT_DIR=output/$TARGET_DIR_NAME"
    echo "#CONFIG=${RK_BUILD_CONFIG}_defconfig"
    echo
    echo "==========================================="

    # RK_BUILD_CONFIG就是前面执行./envsetup.sh时选择的combo,如rockchip_rk3588.
    # 此处make会执行/buildroot目录下的Makefile文件,-C表示进入buildroot目录下,O=表示将编译结果输出到$TARGET_OUTPUT_DIR变量下,
    # 最后一个参数表示编译目标为rockchip_rk3588_defconfig
    # TAG(A)
    make -C ${BUILDROOT_DIR} O="$TARGET_OUTPUT_DIR" \
        "$RK_BUILD_CONFIG"_defconfig
    # 上面的命令执行完毕,会在builtroot目录下生成.config文件。

    CONFIG=${TARGET_OUTPUT_DIR}/.config

    # 复制.config文件为.config.new文件。
    cp ${CONFIG}{,.new}

    # 如果.config.old文件不存在return,否则将.config.old重命名为.config文件.
    mv ${CONFIG}{.old,} &>/dev/null || return 0

    # 根据当前的.config(old config)重新生成.config
    make -C ${BUILDROOT_DIR} O="$TARGET_OUTPUT_DIR" olddefconfig &>/dev/null

    # 如果新生成的.config与(old config)生成的.config文件不一致,则提示是否覆盖旧的config。
    if ! diff ${CONFIG}{,.new}; then
        read -t 10 -p "Found old config, override it? (y/n):" YES
        [ "$YES" = "n" ] || cp ${CONFIG}{.new,}
    fi
}

对上面TAG(A)的流程进行分析
make -C ${BUILDROOT_DIR} O="$TARGET_OUTPUT_DIR" \ "$RK_BUILD_CONFIG"_defconfig,编译目标为rockchip_rk3588_defconfig.

1.实际Makefile是没有rockchip_rk3588_defconfig这个目标的,采用的是一种通用的写法。
Makefile的最后面:.PHONY: $(noconfig_targets)


1-1)接着分析BUILD_DIR变量是如何赋值的

ifneq ("$(origin O)", "command line")
ifneq ($(TARGET_OUTPUT_DIR),)
O := $(TARGET_OUTPUT_DIR)
else
O := $(CURDIR)/output
endif
endif

# Remove the trailing '/.' from $(O) as it can be added by the makefile wrapper
# installed in the $(O) directory.
# Also remove the trailing '/' the user can set when on the command line.
override O := $(patsubst %/,%,$(patsubst %.,%,$(O)))

CANONICAL_O := $(shell mkdir -p $(O) >/dev/null 2>&1)$(realpath $(O))

# Make sure O= is passed (with its absolute canonical path) everywhere the
# toplevel makefile is called back.
EXTRAMAKEARGS := O=$(CANONICAL_O)

# Check Buildroot execution pre-requisites here.
ifneq ($(shell umask):$(CURDIR):$(O),$(REQ_UMASK):$(CANONICAL_CURDIR):$(CANONICAL_O))
BASE_DIR := $(CANONICAL_O)
...
BUILD_DIR := $(BASE_DIR)/build

make时定义了变量TARGET_OUTPUT_DIR为/buildroot/output/rockchip_rk3588,那么
BUILD_DIR即为/buildroot/output/rockchip_rk3588/build.
$(1):表示/buildroot目录
TOPDIR:表示/buildroot目录
一、依赖文件

$(BUILD_DIR)/buildroot-config/conf $(1)/configs/%_defconfig outputmakefile:注意这里有3个依赖,前面2个是文件,最后一个outputmakefile是伪目标。

1.conf文件的生成过程
http://xinyiworld.top/wordpress_it/?p=7722

2.outputmakefile伪目标

outputmakefile:
ifeq ($(NEED_WRAPPER),y)
    $(Q)$(TOPDIR)/support/scripts/mkmakefile $(TOPDIR) $(O)
endif

可以看到伪目标在TARGET_OUTPUT_DIR目录下生成了Makefile文件。

二、命令

命令1:

$(TOPDIR)/build/defconfig_hook.py -m $(1)/configs/$$@ $(BASE_DIR)/.rockchipconfig:执行python脚本

打印一下脚本接收的参数:

这个python脚本主要是采用递归的方法,将/buildroot/configs/rockchip_rk3588_defconfig配置文件及其include的config文件的内容合并到/buildroot/output/rockchip_rk3588/.rockchipconfig文件里,并且把所有config的BR2_ROOTFS_OVERLAY属性值合并到一起用空格分开,BR2_ROOTFS_OVERLAY代表这些目录下的文件会原封不动的拷贝到/buildroot/output/rockchip_rk3588/target目录下。

命令2:

$$(COMMON_CONFIG_ENV) BR2_DEFCONFIG=$(1)/configs/$$@ $$< --defconfig=$(BASE_DIR)/.rockchipconfig $$(CONFIG_CONFIG_IN)

这个命令有些复杂,先把相关的变量打印直观看一下:

$$(COMMON_CONFIG_ENV) BR2_DEFCONFIG=$(1)/configs/$$@ :设置变量

$$< --defconfig=$(BASE_DIR)/.rockchipconfig $$(CONFIG_CONFIG_IN):执行conf,生成.config文件。


最后,再梳理一下lunch_rockchip的流程:

调用源码目录下的Makefile,调用buildroot目录下的Makefile,执行伪目标%_defconfig,生成conf工具并生成.config配置文件。
  • build.sh
    通过./build.sh -h查看有哪些编译目标选项
    如果build.sh不带任何参数,默认执行allsave选项。
    OPTIONS="${@:-allsave}"

一般先要执行./build.sh lunch配置dts,而后再进行各个模块的编译。

这里会将选择的板子型号与/device/rockchip/.BoardConfig.mk建立软连接

/device/rockchip/.BoardConfig.mk

编译日志分析

1.uboot编译日志

./build.sh uboot会执行build.sh文件中的build_uboot()方法

root@xinyi:/home/xinyi/android/code/Task1-debian/rk3588_source# ./build.sh uboot
processing option: uboot
============Start building uboot============
TARGET_UBOOT_CONFIG=rk3588
=========================================
## make rk3588_defconfig -j16
#
# configuration written to .config
#
scripts/kconfig/conf  --silentoldconfig Kconfig
  CHK     include/config.h
  CFG     u-boot.cfg
  GEN     include/autoconf.mk.dep
  CFG     spl/u-boot.cfg
  CFG     tpl/u-boot.cfg
  GEN     spl/include/autoconf.mk
  GEN     tpl/include/autoconf.mk
  GEN     include/autoconf.mk
  CHK     include/config/uboot.release
  CHK     include/generated/timestamp_autogenerated.h
  UPD     include/generated/timestamp_autogenerated.h
  CHK     include/config.h
  CFG     u-boot.cfg
  UPD     include/config/uboot.release
  CHK     include/generated/version_autogenerated.h
  UPD     include/generated/version_autogenerated.h
  CHK     include/generated/generic-asm-offsets.h
  CHK     include/generated/asm-offsets.h
  HOSTCC  tools/mkenvimage.o
  HOSTCC  tools/fit_image.o
  HOSTCC  tools/image-host.o
  HOSTCC  tools/dumpimage.o
  HOSTCC  tools/mkimage.o
  HOSTCC  tools/rockchip/boot_merger.o
  HOSTCC  tools/rockchip/loaderimage.o
  HOSTLD  tools/mkenvimage
tools/rockchip/boot_merger.c: In function ‘main’:
tools/rockchip/boot_merger.c:895:11: warning: array subscript 20 is outside array bounds of ‘char[20]’ [-Warray-bounds]
  895 |  str[len] = 0;
      |  ~~~~~~~~~^~~
tools/rockchip/boot_merger.c:933:7: note: while referencing ‘name’
  933 |  char name[MAX_NAME_LEN];
      |       ^~~~
  HOSTLD  tools/loaderimage
  HOSTLD  tools/boot_merger
  HOSTLD  tools/dumpimage
  HOSTLD  tools/mkimage
  CC      arch/arm/cpu/armv8/fwcall.o
  CC      drivers/usb/gadget/f_fastboot.o
  LD      arch/arm/cpu/armv8/built-in.o
  CC      common/main.o
  LD      common/built-in.o
  CC      cmd/version.o
  LD      cmd/built-in.o
  CC      lib/display_options.o
  LD      lib/built-in.o
  LD      drivers/usb/gadget/built-in.o
  LD      u-boot
  OBJCOPY u-boot.srec
  OBJCOPY u-boot-nodtb.bin
  SYM     u-boot.sym
start=$(/home/xinyi/android/code/Task1-debian/rk3588_source/prebuilts/gcc/linux-x86/aarch64/gcc-arm-10.3-2021.07-x86_64-aarch64-none-linux-gnu/bin/aarch64-none-linux-gnu-nm u-boot | grep __rel_dyn_start | cut -f 1 -d ' '); end=$(/home/xinyi/android/code/Task1-debian/rk3588_source/prebuilts/gcc/linux-x86/aarch64/gcc-arm-10.3-2021.07-x86_64-aarch64-none-linux-gnu/bin/aarch64-none-linux-gnu-nm u-boot | grep __rel_dyn_end | cut -f 1 -d ' '); tools/relocate-rela u-boot-nodtb.bin 0x00200000 $start $end
make[2]: “arch/arm/dts/rk3588-evb.dtb”已是最新。
  CAT     u-boot-dtb.bin
  MKIMAGE u-boot.img
  COPY    u-boot.dtb
  MKIMAGE u-boot-dtb.img
  COPY    u-boot.bin
  ALIGN   u-boot.bin
  COPY    spl/u-boot-spl.dtb
  CC      spl/common/spl/spl.o
  CC      tpl/arch/arm/cpu/armv8/fwcall.o
  CC      tpl/arch/arm/mach-rockchip/tpl.o
  LD      tpl/arch/arm/cpu/armv8/built-in.o
  CC      spl/arch/arm/cpu/armv8/fwcall.o
  LD      spl/arch/arm/cpu/armv8/built-in.o
  LD      tpl/arch/arm/mach-rockchip/built-in.o
  CC      spl/lib/display_options.o
  LD      spl/lib/built-in.o
  LD      tpl/u-boot-tpl
  LD      spl/common/spl/built-in.o
  OBJCOPY tpl/u-boot-tpl-nodtb.bin
  COPY    tpl/u-boot-tpl.bin
  LD      spl/u-boot-spl
  OBJCOPY spl/u-boot-spl-nodtb.bin
  CAT     spl/u-boot-spl-dtb.bin
  COPY    spl/u-boot-spl.bin
  CFGCHK  u-boot.cfg
SEC=1
pack u-boot.itb okay! Input: /home/xinyi/android/code/Task1-debian/rk3588_source/rkbin/RKTRUST/RK3588TRUST.ini

FIT description: FIT Image with ATF/OP-TEE/U-Boot/MCU
Created:         Fri Sep 30 15:58:49 2022
 Image 0 (uboot)
  Description:  U-Boot
  Created:      Fri Sep 30 15:58:49 2022
  Type:         Standalone Program
  Compression:  uncompressed
  Data Size:    1209856 Bytes = 1181.50 KiB = 1.15 MiB
  Architecture: AArch64
  Load Address: 0x00200000
  Entry Point:  unavailable
  Hash algo:    sha256
  Hash value:   0459350cd91ca27a265308d22a864caaf33b1ee98b3614ca76d7ef278d57b169
 Image 1 (atf-1)
  Description:  ARM Trusted Firmware
  Created:      Fri Sep 30 15:58:49 2022
  Type:         Firmware
  Compression:  uncompressed
  Data Size:    186688 Bytes = 182.31 KiB = 0.18 MiB
  Architecture: AArch64
  Load Address: 0x00040000
  Hash algo:    sha256
  Hash value:   5ae6932916e5275236ed293d074bcc75bdea046c36e6c7be147a015bf1d9c0fc
 Image 2 (atf-2)
  Description:  ARM Trusted Firmware
  Created:      Fri Sep 30 15:58:49 2022
  Type:         Firmware
  Compression:  uncompressed
  Data Size:    28672 Bytes = 28.00 KiB = 0.03 MiB
  Architecture: AArch64
  Load Address: 0x000f0000
  Hash algo:    sha256
  Hash value:   c00c7fd75b913cf44d12a27e172513124eaeec71b4448b41aa1c295c05907b3f
 Image 3 (atf-3)
  Description:  ARM Trusted Firmware
  Created:      Fri Sep 30 15:58:49 2022
  Type:         Firmware
  Compression:  uncompressed
  Data Size:    20480 Bytes = 20.00 KiB = 0.02 MiB
  Architecture: AArch64
  Load Address: 0xff100000
  Hash algo:    sha256
  Hash value:   71c3a5841b733b001fe1defcc4d268af37dab96c503c4c71c9c5daa714d3fdd5
 Image 4 (atf-4)
  Description:  ARM Trusted Firmware
  Created:      Fri Sep 30 15:58:49 2022
  Type:         Firmware
  Compression:  uncompressed
  Data Size:    8192 Bytes = 8.00 KiB = 0.01 MiB
  Architecture: AArch64
  Load Address: 0xff001000
  Hash algo:    sha256
  Hash value:   2301cf73be91bb638ecd9c296d6674b9d52696a3825745070c92e21e79c8be24
 Image 5 (optee)
  Description:  OP-TEE
  Created:      Fri Sep 30 15:58:49 2022
  Type:         Firmware
  Compression:  uncompressed
  Data Size:    461200 Bytes = 450.39 KiB = 0.44 MiB
  Architecture: AArch64
  Load Address: 0x08400000
  Hash algo:    sha256
  Hash value:   4ed9cd20b57f71e3b751bc9c0129d74c371e5633ed32a89c6ef42b7a22b59fa2
 Image 6 (fdt)
  Description:  U-Boot dtb
  Created:      Fri Sep 30 15:58:49 2022
  Type:         Flat Device Tree
  Compression:  uncompressed
  Data Size:    7829 Bytes = 7.65 KiB = 0.01 MiB
  Architecture: AArch64
  Hash algo:    sha256
  Hash value:   c07f4a4d713c2dde198a1c4fc7a980a98f5dc97665e3171dc7c319d7846dc381
 Default Configuration: 'conf'
 Configuration 0 (conf)
  Description:  rk3588-evb
  Kernel:       unavailable
  Firmware:     atf-1
  FDT:          fdt
  Loadables:    uboot
                atf-2
                atf-3
                atf-4
                optee
********boot_merger ver 1.2********
Info:Pack loader ok.
pack loader okay! Input: /home/xinyi/android/code/Task1-debian/rk3588_source/rkbin/RKBOOT/RK3588MINIALL.ini
/home/xinyi/android/code/Task1-debian/rk3588_source/u-boot

Image(no-signed, version=0): uboot.img (FIT with uboot, trust...) is ready
Image(no-signed): rk3588_spl_loader_v1.07.111.bin (with spl, ddr...) is ready
pack uboot.img okay! Input: /home/xinyi/android/code/Task1-debian/rk3588_source/rkbin/RKTRUST/RK3588TRUST.ini

Platform RK3588 is build OK, with new .config(make rk3588_defconfig -j16)
/home/xinyi/android/code/Task1-debian/rk3588_source/prebuilts/gcc/linux-x86/aarch64/gcc-arm-10.3-2021.07-x86_64-aarch64-none-linux-gnu/bin/aarch64-none-linux-gnu-
Fri Sep 30 15:58:49 CST 2022
Running build_uboot succeeded.

执行流程:

build.sh ---> build_uboot(),进入uboot目录,执行make.sh脚本。

uboot的make.sh脚本执行流程

执行process_args方法

注意此方法是一个参数一个参数地依次执行,第一个参数是rk3588,第二个参数是CROSS_COMPILE=*。

解析第一个参数rk3588

  • 》》》执行fit.sh,基本上啥事儿没有干。

  • 》》》通过KConfig系统生成uboot的配置文件.config
    make rk3588_defconfig
    会打印

    #
    # configuration written to .config
    #

在Makefile中对应的目标为:

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

目标:scripts_basic

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

http://xinyiworld.top/wordpress_it/?p=8101 可知,$(Q)$(MAKE) $(build)=scripts/basic相当于执行u-boot/scripts/Makefile.build中的__build伪目标,依赖项即为$(always),此变量$(always)通过Makefile.build中include scripts/basic目录下的Makefile文件,值即为fixdep

目标:fixdep
https://www.pianshen.com/article/8257930864/ (fixdep工具的生成过程)
https://blog.csdn.net/guyongqiangx/article/details/52588409 (fixdep工具的调用)
fixdep是KBuild中一种非常重要的机制,该工具的作用就是在编译过程中产生依赖信息,判断依赖目标是不是更新的。

此处outputmakefile并没有执行任何有效操作

FORCE是强制执行目标的机制

最终执行的是$(Q)$(MAKE) $(build)=scripts/kconfig $@,即执行scripts/kconfig下的rk3588_defconfig目标:

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

$(SRCARCH)是..,最终--defconfig指向的是u-boot/configs/rk3588_defconfig文件,最终走向了Kbuild系统。

尝试在u-boot里直接运行conf生成配置文件
会报这个错误,不知道是什么个原理。

目标:include/config/%.conf

执行select_toolchain方法

主要是去指定一些prebuilts目录下的交叉编译工具

执行fixup_platform_configure方法

有个方法得关注一下

function filt_val()
{
    sed -n "/${1}=/s/${1}=//p" $2 | tr -d '\r' | tr -d '"'
}

这个方法的作用是根据key去.config文件里查找value,并去除回车符、引号。

执行select_ini_file方法

选择.ini文件

make (**)

http://xinyiworld.top/wordpress_it/?p=8062

分类: rk3588_bmc

0 条评论

发表回复

您的电子邮箱地址不会被公开。