RDK X5 镜像工程采用单一入口脚本 build.sh 统揽从源码同步到最终 .img 产出的全生命周期构建流程。该脚本通过显式子命令将复杂的嵌入式镜像编译过程拆分为可独立执行、可组合编排的阶段,使开发者既能按需增量编译,也能一键完成从零到镜像的完整构建。本文档聚焦该入口脚本的子命令解析机制、各阶段职责边界以及典型调用链的协作关系,帮助中级开发者建立对构建系统编排逻辑的系统性认知。
构建入口与子命令体系
build.sh 作为全量构建的唯一入口,以第 1 个位置参数作为子命令标识,后续通过 getopts 捕获选项。脚本预设了 8 个子命令,覆盖环境准备、内核编译、引导程序、根文件系统、Deb 包编译、镜像打包以及它们的组合阶段。所有子命令均以 do_ 前缀的函数实现,最终由 case 分支统一调度。
| 子命令 | 职责 | 调用的下级脚本/目录 |
|---|---|---|
setup |
安装构建依赖、下载交叉工具链、执行 repo init & sync |
系统包管理器、repo 工具 |
kernel |
编译标准内核 + RT 实时内核 | mk_kernel.sh、mk_kernel_rt.sh |
bootloader |
编译 miniboot/uboot 并生成 nand_disk.img |
source/bootloader/build/xbuild.sh |
rootfs |
构建 Ubuntu samplefs 并解压为 sysroot | samplefs/make_ubuntu_samplefs.sh |
debs |
本地编译所有平台 Deb 包 | mk_debs.sh |
pack |
安装 Deb 包到 rootfs 并生成最终 .img |
pack_image.sh |
image |
组合阶段:kernel + bootloader + debs + pack | 上述脚本链 |
all |
完整流程:setup + kernel + bootloader + rootfs + debs + pack | 上述全部 |
默认配置文件为 build_params/ubuntu-22.04_desktop_rdk-x5_release.conf,可通过 -c 选项覆盖为 Server 版或其他变体配置。脚本强制要求以 root 权限执行,因为后续挂载 loop 设备、chroot 安装 Deb 包等操作需要特权支持。
子命令解析机制
build.sh 的参数解析遵循 Bash 经典的两阶段模式:先提取位置参数中的子命令,再通过 getopts 扫描选项。第一阶段将 ${1} 赋值给 COMMAND 并立即 shift,确保 getopts 只处理剩余参数;第二阶段使用 while getopts ":c:h" opt 循环,支持 -c config_file 指定构建配置和 -h 打印帮助信息。若传入未知选项,脚本会输出错误并调用 show_help 后退出状态码 1。解析完成后,脚本在执行任何实际构建前会先校验 whoami 是否为 root,避免在编译中途因权限不足而失败。
flowchart TD
A[执行 build.sh] --> B{是否存在 $1?}
B -- 否 / -h --> C[调用 show_help 退出]
B -- 是 --> D[提取 COMMAND 并 shift]
D --> E[getopts 解析 -c / -h]
E --> F{是否为 root?}
F -- 否 --> G[报错退出]
F -- 是 --> H[case 分发到 do_* 函数]
H --> I[执行对应构建阶段]
pack_image.sh 作为 pack 子命令的实际执行者,也独立实现了类似的选项解析逻辑,额外支持 -l 标志以启用本地构建模式,跳过从远程仓库下载 samplefs 和预编译 Deb 包的过程。该脚本首先将 DEFAULT_CONFIG 硬编码为桌面版配置,再允许 -c 覆盖,从而保证在直接调用 pack_image.sh 时仍有合理的默认值。
Sources: build.sh, pack_image.sh
典型构建流程与脚本编排
image 子命令:增量构建的典型路径
对于已完成环境准备(setup)和根文件系统(rootfs)的开发者,最常用的是 image 子命令。它按严格顺序串行执行 do_kernel、do_bootloader、do_debs、do_pack,形成一条从源码到镜像的完整流水线。该组合不重复执行环境准备和 rootfs 构建,适合内核或 Deb 包源码发生变更后的快速迭代。
flowchart LR
subgraph image [image 子命令]
K[kernel<br/>mk_kernel.sh<br/>mk_kernel_rt.sh] --> B[bootloader<br/>xbuild.sh]
B --> D[debs<br/>mk_debs.sh]
D --> P[pack<br/>pack_image.sh]
end
do_kernel 依次调用 mk_kernel.sh 与 mk_kernel_rt.sh,分别基于 source/kernel 和 source/kernel-rt 编译标准内核与 RT 内核,输出 Image、Image-rt、dtb 及内核模块到 deploy/kernel/。do_bootloader 则进入 source/bootloader/build 执行 xbuild.sh lunch 0 && xbuild.sh,并将产出的 nand_disk.img 按日期命名后复制到 hobot-miniboot 固件目录,供后续 Deb 包打包使用。
Sources: build.sh, build.sh, mk_kernel.sh, mk_kernel_rt.sh
all 子命令:从零到镜像的完整构建
all 子命令在 image 的基础上前置了 setup 和 rootfs,构成真正意义上的全量构建。do_rootfs 调用 samplefs/make_ubuntu_samplefs.sh desktop 生成基础 Ubuntu samplefs,随后将其复制到 rootfs/ 目录,并解压一份到 deploy/rootfs/ 作为交叉编译 sysroot。这份 sysroot 对 debs 阶段至关重要——例如 hobot-spdev 等包在交叉编译时需要目标系统的头文件和库文件,若 deploy/rootfs/usr/include/string.h 缺失,do_debs 会主动报错并提示先执行 rootfs。
flowchart TD
A[all] --> S[setup<br/>依赖/工具链/repo]
S --> K[kernel<br/>标准+RT]
K --> B[bootloader<br/>miniboot/uboot]
B --> R[rootfs<br/>samplefs + sysroot]
R --> D[debs<br/>并行编译Deb包]
D --> P[pack<br/>分区/烧录镜像]
Sources: build.sh, build.sh, build.sh
内核与 Deb 包的编译子系统
内核编译的标准化封装
mk_kernel.sh 与 mk_kernel_rt.sh 在内核编译流程上高度同源,均通过 CROSS_COMPILE 和 ARCH 环境变量锁定 aarch64-none-linux-gnu- 交叉工具链。脚本首先读取 .rdk_config 获取 RDK_SOC_NAME,再据此选择对应的 defconfig、内核源码目录及版本号。编译流程遵循严格的四步顺序:生成 .config、编译 Image dtbs、编译 modules、安装模块到 deploy/kernel/modules/。对于 X5 平台,两者还会额外编译 hobot-drivers/bpu-hw_io 外部模块并执行 modules_depmod 生成模块依赖关系。RT 内核脚本在首次执行时会自动从标准内核源码复制一份到 source/kernel-rt,并打上 patch-6.1.83-rt28.patch 及 gs_usb.patch,实现源码级实时化。
Sources: mk_kernel.sh, mk_kernel_rt.sh
Deb 包的并行编译与单包构建
mk_debs.sh 根据 .rdk_config 中的 RDK_SOC_NAME 选择 X5 或 X3 的包列表,X5 默认包含 17 个 Deb 包,涵盖内核镜像、头文件、设备树、BPU 驱动、多媒体、相机、DNN 运行时及系统配置等。脚本的主逻辑分为无参全量模式和单参数模式两种:
- 全量模式:清空
deploy/deb_pkgs/,基于MAX_JOBS(默认为nproc)限制并行度,将每个包的编译作为后台任务启动,并重定向日志到.deb_build_logs/<pkg_name>.log。主循环通过kill -0轮询检测子进程状态,任一失败即输出最后 20 行日志并终止整体构建。全部成功后,所有.deb与.log被复制到deb_packages/目录。 - 单包模式:直接匹配参数名并执行
make_debian_deb,适用于精准调试单个包的编译问题。
每个包的构建逻辑封装在巨大的 case 分支中,统一执行控制文件生成、版权信息写入、md5sum 计算、安装大小统计,最终由 fakeroot dpkg -b 打包。
Sources: mk_debs.sh, mk_debs.sh
镜像打包与根文件系统定制
pack_image.sh 是构建流程的最后关卡,其核心函数 make_ubuntu_image 负责将分散的产出物整合为可烧录的 .img。流程首先解压 rootfs/samplefs_desktop_*.tar.gz 到临时构建目录,随后调用 hobot_customize_rootfs.sh 执行系统级定制:配置主机名、SSH root 登录、NetworkManager、禁用自动升级、创建用户及权限组等。接着脚本将 deb_packages/、third_packages/ 以及 deploy/deb_pkgs/ 中的 .deb 统一收集到 /app/hobot_debs,通过 dpkg 在 chroot 环境中安装,并自动剔除旧版本保留最新版。
安装完成后,脚本基于 rootfs 实际大小计算分区参数:CONFIG 分区固定 256 MiB,rootfs 分区则在实际大小基础上增加 20% 余量再加 200 MiB,并以 4 MiB 对齐。通过 truncate 创建空镜像文件,parted 建立 MBR 分区表,losetup 挂载为 loop 设备,分别格式化为 FAT32(CONFIG)和 ext4(rootfs)。最终使用 rsync 将定制后的 rootfs 同步到 ext4 分区,将 config/ 下的板级配置同步到 FAT32 分区。卸载后输出镜像文件,并由 do_pack 补充生成 SHA256 校验和与 ZIP 压缩包。
Sources: pack_image.sh, hobot_customize_rootfs.sh, build.sh
配置文件的层次与优先级
构建系统存在两层配置:.rdk_config 与 build_params/*.conf。.rdk_config 仅定义 RDK_SOC_NAME(x3 或 x5),被 mk_kernel.sh、mk_kernel_rt.sh、mk_debs.sh 等子脚本 source 加载,决定源码路径、包列表及平台相关逻辑。rdk_env.sh 提供交互式方式生成该文件,方便首次建仓时选择目标 SoC。
build_params/*.conf 则由 build.sh 和 pack_image.sh 加载,定义镜像名称、samplefs 下载地址、Ubuntu 版本、Deb 包列表等发行级参数。build.sh 的默认值为 ubuntu-22.04_desktop_rdk-x5_release.conf,开发者可通过 -c 切换为 Server 版或 Beta 版配置,实现同一套脚本产出不同形态镜像的能力。pack_image.sh 在 LOCAL_BUILD="false" 时会依据该配置中的 RDK_SAMPLEFS_URL 和 RDK_ARCHIVE_URL 远程下载基础 rootfs 和预编译 Deb 包,而在本地迭代时通过 -l 跳过下载,直接使用 rootfs/ 和 deb_packages/ 下的本地产物。
Sources: .rdk_config, rdk_env.sh, build_params/ubuntu-22.04_desktop_rdk-x5_release.conf, pack_image.sh
阅读路径与后续步骤
理解全量构建与子命令解析后,建议继续深入各子系统的实现细节。若关注内核层面的双版本编译与实时补丁机制,可阅读 双内核编译与实时内核;若需了解 Deb 包的具体编译逻辑、依赖声明与并行调度策略,可阅读 Deb 包本地编译与依赖管理;若对镜像分区的精确计算、loop 设备挂载及系统定制脚本感兴趣,可阅读 镜像打包与系统定制;而构建参数的完整语义与多配置管理策略则在 构建配置与参数管理 中有更详尽的阐述。