RK3576 Android15 构建脚本(build.sh)全解析 电子说
一、脚本整体定位
该脚本是瑞芯微RK3576平台基于Android 15的自动化构建脚本,整合了UBoot、Kernel(含驱动)、Android系统、OTA包、update.img固件等全流程构建逻辑,是平台固件编译的核心入口。开发者掌握该脚本,能精准控制编译流程、定位编译失败点、定制化构建策略(如仅编译内核/UBoot、调整编译参数),是RK3576 Android开发调试的核心抓手。

二、脚本核心知识点拆解
1. 脚本基础框架(Shell脚本核心)
•脚本头声明:#!/bin/bash 声明脚本使用Bash解释器执行,是Linux Shell脚本的标准开头。
•用法函数(usage):定义脚本参数说明,当传入非法参数或执行-h/--help(隐式)时打印用法并退出,提升脚本易用性。
○知识点:Shell函数定义、echo输出格式化、exit退出码(exit 1表示异常退出)。
2. 变量初始化(构建参数预设)
脚本开头定义了一系列布尔型/字符型变量,作为构建开关和参数容器:
|
变量名
|
作用
|
|
BUILD_UBOOT
|
UBoot编译开关(默认false)
|
|
BUILD_KERNEL_WITH_CLANG
|
内核是否用Clang编译(默认false)
|
|
BUILD_KERNEL
|
内核编译开关(默认false)
|
|
BUILD_ANDROID
|
Android系统编译开关(默认false)
|
|
BUILD_UPDATE_IMG
|
update.img固件打包开关(默认false)
|
|
BUILD_OTA
|
OTA升级包编译开关(默认false)
|
|
BUILD_PACKING
|
编译产物归档开关(默认false)
|
|
KERNEL_DTS
|
内核设备树文件名(默认空,后续从环境变量读取)
|
|
BUILD_JOBS
|
编译并行任务数(默认16,控制make -j的并发数)
|
•知识点:Shell变量赋值、布尔型变量的Shell表达(true/false为字符串,非原生布尔)。
3. 命令行参数解析(getopts)
while getopts "UCKABpouvV" argdocase $arg inU) BUILD_UBOOT=true ;;C) BUILD_KERNEL=true; BUILD_KERNEL_WITH_CLANG=true ;;# ... 其他参数处理?) usage ;; # 非法参数调用usageesacdone
•核心知识点:getopts是Shell内置的参数解析工具,支持短参数(如-U、-K)解析:
○UCKABpouvV 中,带:的字符(如v)表示参数后需跟值(如-v userdebug);
○case分支匹配参数,实现“参数→变量”的映射;
○非法参数触发usage函数,保证参数合法性。
4. 环境前置检查与初始化
(1)编译环境校验
if [ -z "$TARGET_RELEASE" ]; thenecho "Please lunch your product first! e.g."echo "source build/envsetup.sh"echo "lunch rk3588_u-trunk_staging-userdebug"(return 1 2>/dev/null) || exit 1fi
•知识点:
○[ -z "$VAR" ] 检查变量是否为空;
○TARGET_RELEASE是Android编译环境的核心变量,需通过lunch命令初始化,脚本强制要求先执行source build/envsetup.sh && lunch,避免环境缺失导致编译失败;
○(return 1 2>/dev/null) || exit 1 兼容脚本“source执行”和“直接执行”两种场景(source执行时return,直接执行时exit)。
(2)编译工具链配置
•知识点:
○export设置环境变量,作用于当前Shell及子进程;
○Android编译对JDK/Clang版本强依赖,脚本固化路径避免版本错误;
○ANDROID_BUILD_TOP是Android源码顶层路径,由envsetup.sh定义。
(3)Android编译变量读取
BUILD_NUMBER=`get_build_var BUILD_NUMBER`UBOOT_DEFCONFIG=`get_build_var PRODUCT_UBOOT_CONFIG`KERNEL_DEFCONFIG=`get_build_var PRODUCT_KERNEL_CONFIG`
•知识点:
○get_build_var是Android编译系统的工具函数,用于读取Android.mk/BoardConfig.mk中定义的变量;
○脚本通过该方式动态获取产品配置(如UBoot默认配置、内核defconfig),而非硬编码,适配多产品/多版本。
5. 分模块编译逻辑
(1)UBoot编译
if [ "$BUILD_UBOOT" = true ] ; thencd u-boot && make clean && make mrproper && make distclean && make $UBOOT_DEFCONFIG && ./make.sh && cd -if [ $? -eq 0 ]; thenecho "Build uboot ok!"elseecho "Build uboot failed!"exit 1fifi
•核心知识点:
○make clean/mrproper/distclean:UBoot编译清理,逐步清理临时文件/配置/编译产物,保证编译环境干净;
○make $UBOOT_DEFCONFIG:加载UBoot默认配置(如rk3576_defconfig);
○./make.sh:瑞芯微定制的UBoot编译脚本(替代原生make);
○$? -eq 0:检查上一条命令的退出码(0为成功,非0为失败),失败则立即退出脚本,避免无效编译。
(2)Kernel编译(含驱动)
① 编译器适配(Clang/GCC)
if [ "$BUILD_KERNEL_WITH_CLANG" = true ] ; thenif [ "$KERNEL_ARCH" = "arm64" ]; thenADDON_ARGS="CROSS_COMPILE=aarch64-linux-gnu- LLVM=1 LLVM_IAS=1"elseADDON_ARGS="CC=clang LD=ld.lld"fifi
•知识点:
○ARM64架构内核用Clang编译时,需指定LLVM=1 LLVM_IAS=1(启用LLVM汇编器);
○32位ARM架构直接指定CC=clang LD=ld.lld;
○ADDON_ARGS整合编译参数,后续传递给make,实现参数复用。
② 内核主编译
cd $LOCAL_KERNEL_PATH && make clean && make $ADDON_ARGS ARCH=$KERNEL_ARCH $KERNEL_DEFCONFIG && make $ADDON_ARGS ARCH=$KERNEL_ARCH $KERNEL_DTS.img -j$BUILD_JOBS && cd -
•知识点:
○$LOCAL_KERNEL_PATH:内核源码路径(如kernel-5.10),由PRODUCT_KERNEL_VERSION动态获取;
○$KERNEL_DTS.img:编译指定设备树的内核镜像(RK平台内核镜像与DTS绑定);
○-j$BUILD_JOBS:并行编译,默认16线程,可通过-J参数调整,平衡编译速度与系统负载。
③ 外设驱动编译(WiFi/摄像头)
•WiFi驱动:编译external/wifi_driver路径下的驱动,生成.ko文件并剥离调试信息(llvm-strip --strip-debug);
•摄像头驱动:编译hardware/rockchip/rvcam/drivers路径下的驱动,拷贝到预编译目录;
•知识点:内核模块(.ko)编译需指定M=$PWD(模块源码路径),依赖内核源码的编译环境;llvm-strip剥离调试信息减小文件体积。
(3)Android系统编译
if [ "$BUILD_ANDROID" = true ] ; thenif [ "$BUILD_OTA" = true ] ; then# OTA包编译逻辑:make → make dist → mkimage_ab.sh/mkimage.shelse# 普通编译:make installclean → make -j$BUILD_JOBSfifi
•核心知识点:
○make installclean:清理out目录下的临时产物,保留配置,避免编译缓存导致的问题;
○make dist:生成OTA包所需的target_files.zip(包含系统分区镜像);
○mkimage_ab.sh/mkimage.sh:瑞芯微定制的镜像打包脚本,区分AB分区(无缝更新)和非AB分区;
○每一步编译后检查$?,失败则退出,保证编译链路的可靠性。
(4)固件打包(update.img/OTA)
① update.img打包
if [ "$BUILD_UPDATE_IMG" = true ] ; thencp -f $IMAGE_PATH/* $PACK_TOOL_DIR/rockdev/Image/if [[ $TARGET_PRODUCT =~ "PX30" ]]; thencd $PACK_TOOL_DIR/rockdev && ./mkupdate.sh px30 Image# ... 其他平台适配fimv $PACK_TOOL_DIR/rockdev/update.img $IMAGE_PATH/ -ffi
•知识点:
○PACK_TOOL_DIR=RKTools/linux/Linux_Pack_Firmware:瑞芯微官方打包工具路径;
○mkupdate.sh:根据平台(PX30/RK356x/RK3576)调用不同的打包逻辑,生成可用于量产的update.img;
○正则匹配[[ $TARGET_PRODUCT =~ "PX30" ]]:适配多产品平台,提升脚本通用性。
② OTA包打包
•非AB分区:make dist生成target_files.zip → mkimage.sh ota生成OTA.zip;
•AB分区:make dist → mkimage_ab.sh ota生成AB格式OTA包;
•知识点:Android OTA包依赖target_files.zip,包含分区镜像、升级脚本等,是系统空中升级的核心文件。
(5)编译产物归档(BUILD_PACKING)
if [ "$BUILD_PACKING" = true ] ; thenmkdir -p $STUB_PATH/IMAGES/cp $IMAGE_PATH/* $STUB_PATH/IMAGES/# 生成补丁/提交清单/编译命令日志.repo/repo/repo forall -c "$PROJECT_TOP/device/rockchip/common/gen_patches_body.sh"cp out/commit_id.xml $STUB_PATH/manifest_${DATE}.xmlfi
•知识点:
○STUB_PATH:按“产品_版本_时间”命名归档路径,便于版本追溯;
○repo forall:遍历所有Git仓库,执行补丁生成脚本,记录代码修改;
○归档内容包含镜像文件、编译日志、内核配置、Git提交清单,用于版本管理和问题复现。
6. 辅助逻辑(路径/时间/日志)
•路径格式化:STUB_PATH="$(echo $STUB_PATH | tr '[]' '[]')" 将路径转为大写,统一命名规范;
•时间戳:DATE=$(date +%Y%m%d.%H%M) 生成时间戳,用于归档路径和版本标识;
•日志输出:大量echo "-------------------KERNEL_VERSION:$KERNEL_VERSION" 输出关键参数,便于编译过程调试。
三、脚本整体流程图

四、掌握该脚本对开发调试的意义
1. 精准控制编译流程,提升开发效率
•开发阶段无需全量编译:调试UBoot时仅执行./build.sh -U,调试内核时执行./build.sh -K,调试Android时执行./build.sh -A,避免全量编译耗时(RK3576全量编译需1-2小时);
•自定义编译参数:通过-J调整并发数(如低配机器执行./build.sh -A -J 8),通过-v指定编译版本(./build.sh -A -v user),适配不同调试场景。
2. 快速定位编译失败点
•脚本每一步编译后检查$?并输出日志,失败时直接退出并打印原因(如“Build kernel failed!”);
•开发者可根据日志定位失败模块:
○UBoot失败:检查UBOOT_DEFCONFIG是否正确、u-boot/make.sh是否有语法错误;
○Kernel失败:检查KERNEL_DTS是否存在、Clang版本是否匹配、驱动编译依赖;
○Android失败:检查lunch命令是否正确、Android源码是否完整。
3. 定制化适配产品需求
•新增产品/版本:修改PRODUCT_KERNEL_DTS/PRODUCT_UBOOT_CONFIG等变量,或在参数解析分支中新增产品适配逻辑;
•定制固件打包:修改BUILD_PACKING逻辑,添加自定义归档内容(如新增模块的编译产物);
•适配新编译工具:调整Clang/JDK路径,兼容新版编译链(如升级Clang版本时修改clang-r530567为新路径)。
4. 理解RK平台编译体系,掌握量产固件制作
•脚本整合了瑞芯微定制工具([mkupdate.sh](mkupdate.sh)、[pack_resource.sh](pack_resource.sh))和Android原生编译逻辑,是RK平台“源码→量产固件”的完整链路;
•掌握脚本后,可自主制作OTA包、update.img量产固件,适配工厂烧录/用户升级场景;
•归档逻辑(BUILD_PACKING)便于版本管理,调试时可追溯“某版本固件的编译参数/代码提交/内核配置”,快速复现线上问题。
5. 适配AB分区/OTA升级等高级特性
•脚本区分AB分区(BOARD_USES_AB_IMAGE)和非AB分区的编译逻辑,开发者可通过脚本理解Android 15无缝更新(AB OTA)的实现方式;
•掌握OTA包生成流程,可定制升级脚本(如添加分区校验、预安装脚本),满足产品升级需求。
总结
该脚本是RK3576 Android 15平台的“编译总控中心”,涵盖了从环境初始化到固件量产的全流程。开发者掌握其逻辑,不仅能高效调试各模块(UBoot/Kernel/Android),还能定制化适配产品需求,是RK3576平台开发调试的核心技能。同时,脚本的模块化设计、参数解析、错误处理等Shell编程技巧,也为嵌入式Linux/Android开发提供了通用参考。
审核编辑 黄宇
全部0条评论
快来发表一下你的评论吧 !