Skip to content

解析 buildroot 的编译原理

1. 如何调试 shell 脚本

shell
#!/bin/bash -x
PS4='+[${BASH_SOURCE}:${LINENO}] ' # 显示脚本名和行号

build.sh 中的 #!/bin/bash 改为 #!/bin/bash -x 即可在执行时显示执行的命令。PS4='+[${BASH_SOURCE}:${LINENO}] ' 用于显示脚本名和行号。 通过这个方式,我们就可以方便的了解到脚本的执行过程。

2. 构建流程

1. 加载板级配置文件

shell
# 加载板级配置文件
./build.sh lunch

当选择了对应的板级配置后,执行了: ln -rfs /home/lckfb/device/rockchip/rk356x/BoardConfig-rk3566-tspi-v10.mk device/rockchip/.BoardConfig.mk

创建软链接,将板级配置文件复制到

device/rockchip/.BoardConfig.mk
文件中。

这个mk中定义了编译参数,如编译目标系统、编译工具链、编译选项等。例如:

shell
# Target arch
export RK_ARCH=arm64
# Uboot defconfig
export RK_UBOOT_DEFCONFIG=rk3568
# Uboot image format type: fit(flattened image tree)
export RK_UBOOT_FORMAT_TYPE=fit
# 内核 默认配置文件
export RK_KERNEL_DEFCONFIG=rockchip_linux_defconfig
# 内核 设备树
export RK_KERNEL_DTS=rk3568-evb1-ddr4-v10-linux
# 分区表文件
export RK_PARAMETER=parameter-buildroot-fit.txt
# Buildroot 配置文件
export RK_CFG_BUILDROOT=rockchip_rk3568
# Recovery 配置文件
export RK_CFG_RECOVERY=rockchip_rk356x_recovery
# Set ramboot image type
export RK_RAMBOOT_TYPE=
# Set oem partition type, including ext2 squashfs
export RK_OEM_FS_TYPE=ext2
# Set userdata partition type, including ext2, fat
export RK_USERDATA_FS_TYPE=ext2
#OEM config
export RK_OEM_DIR=oem_normal
# Define pre-build script for this board
export RK_BOARD_PRE_BUILD_SCRIPT=app-build.sh

从代码上可以看出:这个配置文件就是定义了各种系统参数.

2. 指定编译目标系统

shell
export RK_ROOTFS_SYSTEM=buildroot

RK_ROOTFS_SYSTEM 是一个环境变量,用于指定编译的目标系统。在这里,我们指定了编译目标为 buildroot。这个环境变量在 build.sh 脚本中被使用,用于确定编译过程中需要执行的命令。

3. 一键全编译

shell
./build.sh all

这个脚本会执行一系列的编译命令,包括编译内核kernel、编译 rootfs、编译 recovery 等。

4. 将全部的镜像都汇总出来

shell
./mkfirmware.sh

这个脚本会将编译出来的镜像文件都汇总到一个文件./rockdev/中,方便我们进行烧录。

5. 打包成一体升级镜像

shell
./build.sh updateimg

这个脚本会生成一个 ./rockdev/update.img 文件,这个文件包含了所有编译的镜像文件,以及各个镜像的分区信息。 只需要烧录这个文件到设备中,就可以完成升级了。

3. 单独编译各个模块

1. 单独编译 uboot

shell
./build.sh uboot
  • 执行:build_uboot函数
  • 调用: ./make.sh $RK_UBOOT_DEFCONFIG $UBOOT_COMPILE_COMMANDS
  • 调用: make PYTHON=python2 CROSS_COMPILE=${TOOLCHAIN} all --jobs=${JOB}
  • 这里的make 实际上就是执行 Makefile 来编译内核。
  • Makefile 的工作过程
  • 生成的镜像文件在: ./uboot/uboot.img

2. 单独编译 kernel

shell
./build.sh kernel
  1. check_config
  2. build_check_cross_compile
  3. cd kerneal
  4. make ARCH=arm64 rockchip_linux_defconfig
  5. make ARCH=arm64 tspi-rk3566-user-v10-linux.img -j12 这个函数主要是编译对应的目录下的Makefile文件
    Makefile 的工作过程
  6. build_check_power_domain 电源域的配置
  7. 生成的镜像文件在: ./kernel/boot.img

3. 单独编译 rootfs

shell
./build.sh buildroot
  1. check_config

  2. build_buildroot

  3. 执行: /home/lckfb/device/rockchip/common/mk-buildroot.sh

  4. 执行:$TOP_DIR/buildroot/utils/brmake

  5. 执行:unbuffer make "${@}"; 这个函数就是执行 /buildroot/Makefile
    Makefile 的工作过程

  6. finish_build

  7. 生成的镜像文件在: ./buildroot/output/images/rootfs.img

4. 单独编译 recovery 镜像

shell
./build.sh recovery
  • 清空所有的配置信息

  • 加载指定的配置信息 source /home/lckfb/device/rockchip/.BoardConfig.mk

  • 指定交叉编译器 /home/lckfb/prebuilts/gcc/linux-x86/aarch64/gcc-arm-10.3-2021.07-x86_64-aarch64-none-linux-gnu

  • 指定默认配置 make ARCH=arm64 rockchip_linux_defconfig

  • 生成 .config

  • 开始编译: make ARCH=arm64 tspi-rk3566-user-v10-linux.img -j12