一、腳本整體定位
該腳本是瑞芯微RK3576平臺(tái)基于Android 15的自動(dòng)化構(gòu)建腳本,整合了UBoot、Kernel(含驅(qū)動(dòng))、Android系統(tǒng)、OTA包、update.img固件等全流程構(gòu)建邏輯,是平臺(tái)固件編譯的核心入口。開(kāi)發(fā)者掌握該腳本,能精準(zhǔn)控制編譯流程、定位編譯失敗點(diǎn)、定制化構(gòu)建策略(如僅編譯內(nèi)核/UBoot、調(diào)整編譯參數(shù)),是RK3576 Android開(kāi)發(fā)調(diào)試的核心抓手。

二、腳本核心知識(shí)點(diǎn)拆解
1.腳本基礎(chǔ)框架(Shell腳本核心)
?腳本頭聲明:#!/bin/bash聲明腳本使用Bash解釋器執(zhí)行,是Linux Shell腳本的標(biāo)準(zhǔn)開(kāi)頭。
?用法函數(shù)(usage):定義腳本參數(shù)說(shuō)明,當(dāng)傳入非法參數(shù)或執(zhí)行-h/--help(隱式)時(shí)打印用法并退出,提升腳本易用性。
?知識(shí)點(diǎn):Shell函數(shù)定義、echo輸出格式化、exit退出碼(exit 1表示異常退出)。
2.變量初始化(構(gòu)建參數(shù)預(yù)設(shè))
腳本開(kāi)頭定義了一系列布爾型/字符型變量,作為構(gòu)建開(kāi)關(guān)和參數(shù)容器:
|
變量名
|
作用
|
|
BUILD_UBOOT
|
UBoot編譯開(kāi)關(guān)(默認(rèn)false)
|
|
BUILD_KERNEL_WITH_CLANG
|
內(nèi)核是否用Clang編譯(默認(rèn)false)
|
|
BUILD_KERNEL
|
內(nèi)核編譯開(kāi)關(guān)(默認(rèn)false)
|
|
BUILD_ANDROID
|
Android系統(tǒng)編譯開(kāi)關(guān)(默認(rèn)false)
|
|
BUILD_UPDATE_IMG
|
update.img固件打包開(kāi)關(guān)(默認(rèn)false)
|
|
BUILD_OTA
|
OTA升級(jí)包編譯開(kāi)關(guān)(默認(rèn)false)
|
|
BUILD_PACKING
|
編譯產(chǎn)物歸檔開(kāi)關(guān)(默認(rèn)false)
|
|
KERNEL_DTS
|
內(nèi)核設(shè)備樹(shù)文件名(默認(rèn)空,后續(xù)從環(huán)境變量讀取)
|
|
BUILD_JOBS
|
編譯并行任務(wù)數(shù)(默認(rèn)16,控制make -j的并發(fā)數(shù))
|
?知識(shí)點(diǎn):Shell變量賦值、布爾型變量的Shell表達(dá)(true/false為字符串,非原生布爾)。
3.命令行參數(shù)解析(getopts)
whilegetopts"UCKABpouvV"argdocase$arginU) BUILD_UBOOT=true;;C) BUILD_KERNEL=true; BUILD_KERNEL_WITH_CLANG=true;;# ... 其他參數(shù)處理?) usage ;;# 非法參數(shù)調(diào)用usageesacdone
?核心知識(shí)點(diǎn):getopts是Shell內(nèi)置的參數(shù)解析工具,支持短參數(shù)(如-U、-K)解析:
?UCKABpouvV中,帶:的字符(如v)表示參數(shù)后需跟值(如-v userdebug);
?case分支匹配參數(shù),實(shí)現(xiàn)“參數(shù)→變量”的映射;
?非法參數(shù)觸發(fā)usage函數(shù),保證參數(shù)合法性。
4.環(huán)境前置檢查與初始化
(1)編譯環(huán)境校驗(yàn)
if[ -z"$TARGET_RELEASE"];thenecho"Please lunch your product first! e.g."echo"source build/envsetup.sh"echo"lunch rk3588_u-trunk_staging-userdebug"(return1 2>/dev/null) ||exit1fi
?知識(shí)點(diǎn):
?[ -z "$VAR" ]檢查變量是否為空;
?TARGET_RELEASE是Android編譯環(huán)境的核心變量,需通過(guò)lunch命令初始化,腳本強(qiáng)制要求先執(zhí)行source build/envsetup.sh && lunch,避免環(huán)境缺失導(dǎo)致編譯失敗;
?(return 1 2>/dev/null) || exit 1兼容腳本“source執(zhí)行”和“直接執(zhí)行”兩種場(chǎng)景(source執(zhí)行時(shí)return,直接執(zhí)行時(shí)exit)。
(2)編譯工具鏈配置
?知識(shí)點(diǎn):
?export設(shè)置環(huán)境變量,作用于當(dāng)前Shell及子進(jìn)程;
?Android編譯對(duì)JDK/Clang版本強(qiáng)依賴,腳本固化路徑避免版本錯(cuò)誤;
?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`
?知識(shí)點(diǎn):
?get_build_var是Android編譯系統(tǒng)的工具函數(shù),用于讀取Android.mk/BoardConfig.mk中定義的變量;
?腳本通過(guò)該方式動(dòng)態(tài)獲取產(chǎn)品配置(如UBoot默認(rèn)配置、內(nèi)核defconfig),而非硬編碼,適配多產(chǎn)品/多版本。
5.分模塊編譯邏輯
(1)UBoot編譯
if["$BUILD_UBOOT"=true] ;thencdu-boot && make clean && make mrproper && make distclean && make$UBOOT_DEFCONFIG&& ./make.sh &&cd-if[ $? -eq 0 ];thenecho"Build uboot ok!"elseecho"Build uboot failed!"exit1fifi
?核心知識(shí)點(diǎn):
?make clean/mrproper/distclean:UBoot編譯清理,逐步清理臨時(shí)文件/配置/編譯產(chǎn)物,保證編譯環(huán)境干凈;
?make $UBOOT_DEFCONFIG:加載UBoot默認(rèn)配置(如rk3576_defconfig);
?./make.sh:瑞芯微定制的UBoot編譯腳本(替代原生make);
?$? -eq 0:檢查上一條命令的退出碼(0為成功,非0為失敗),失敗則立即退出腳本,避免無(wú)效編譯。
(2)Kernel編譯(含驅(qū)動(dòng))
①編譯器適配(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
?知識(shí)點(diǎn):
?ARM64架構(gòu)內(nèi)核用Clang編譯時(shí),需指定LLVM=1 LLVM_IAS=1(啟用LLVM匯編器);
?32位ARM架構(gòu)直接指定CC=clang LD=ld.lld;
?ADDON_ARGS整合編譯參數(shù),后續(xù)傳遞給make,實(shí)現(xiàn)參數(shù)復(fù)用。
②內(nèi)核主編譯
cd$LOCAL_KERNEL_PATH&& make clean && make$ADDON_ARGSARCH=$KERNEL_ARCH$KERNEL_DEFCONFIG&& make$ADDON_ARGSARCH=$KERNEL_ARCH$KERNEL_DTS.img -j$BUILD_JOBS&&cd-
?知識(shí)點(diǎn):
?$LOCAL_KERNEL_PATH:內(nèi)核源碼路徑(如kernel-5.10),由PRODUCT_KERNEL_VERSION動(dòng)態(tài)獲取;
?$KERNEL_DTS.img:編譯指定設(shè)備樹(shù)的內(nèi)核鏡像(RK平臺(tái)內(nèi)核鏡像與DTS綁定);
?-j$BUILD_JOBS:并行編譯,默認(rèn)16線程,可通過(guò)-J參數(shù)調(diào)整,平衡編譯速度與系統(tǒng)負(fù)載。
③外設(shè)驅(qū)動(dòng)編譯(WiFi/攝像頭)
?WiFi驅(qū)動(dòng):編譯external/wifi_driver路徑下的驅(qū)動(dòng),生成.ko文件并剝離調(diào)試信息(llvm-strip --strip-debug);
?攝像頭驅(qū)動(dòng):編譯hardware/rockchip/rvcam/drivers路徑下的驅(qū)動(dòng),拷貝到預(yù)編譯目錄;
?知識(shí)點(diǎn):內(nèi)核模塊(.ko)編譯需指定M=$PWD(模塊源碼路徑),依賴內(nèi)核源碼的編譯環(huán)境;llvm-strip剝離調(diào)試信息減小文件體積。
(3)Android系統(tǒng)編譯
if["$BUILD_ANDROID"=true] ;thenif["$BUILD_OTA"=true] ;then# OTA包編譯邏輯:make → make dist → mkimage_ab.sh/mkimage.shelse# 普通編譯:make installclean → make -j$BUILD_JOBSfifi
?核心知識(shí)點(diǎn):
?make installclean:清理out目錄下的臨時(shí)產(chǎn)物,保留配置,避免編譯緩存導(dǎo)致的問(wèn)題;
?make dist:生成OTA包所需的target_files.zip(包含系統(tǒng)分區(qū)鏡像);
?mkimage_ab.sh/mkimage.sh:瑞芯微定制的鏡像打包腳本,區(qū)分AB分區(qū)(無(wú)縫更新)和非AB分區(qū);
?每一步編譯后檢查$?,失敗則退出,保證編譯鏈路的可靠性。
(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# ... 其他平臺(tái)適配fimv$PACK_TOOL_DIR/rockdev/update.img$IMAGE_PATH/ -ffi
?知識(shí)點(diǎn):
?PACK_TOOL_DIR=RKTools/linux/Linux_Pack_Firmware:瑞芯微官方打包工具路徑;
?mkupdate.sh:根據(jù)平臺(tái)(PX30/RK356x/RK3576)調(diào)用不同的打包邏輯,生成可用于量產(chǎn)的update.img;
?正則匹配[[ $TARGET_PRODUCT =~ "PX30" ]]:適配多產(chǎn)品平臺(tái),提升腳本通用性。
② OTA包打包
?非AB分區(qū):make dist生成target_files.zip →mkimage.sh ota生成OTA.zip;
?AB分區(qū):make dist→mkimage_ab.sh ota生成AB格式OTA包;
?知識(shí)點(diǎn):Android OTA包依賴target_files.zip,包含分區(qū)鏡像、升級(jí)腳本等,是系統(tǒng)空中升級(jí)的核心文件。
(5)編譯產(chǎn)物歸檔(BUILD_PACKING)
if["$BUILD_PACKING"=true] ;thenmkdir-p$STUB_PATH/IMAGES/cp$IMAGE_PATH/*$STUB_PATH/IMAGES/# 生成補(bǔ)丁/提交清單/編譯命令日志.repo/repo/repo forall -c"$PROJECT_TOP/device/rockchip/common/gen_patches_body.sh"cpout/commit_id.xml$STUB_PATH/manifest_${DATE}.xmlfi
?知識(shí)點(diǎn):
?STUB_PATH:按“產(chǎn)品_版本_時(shí)間”命名歸檔路徑,便于版本追溯;
?repo forall:遍歷所有Git倉(cāng)庫(kù),執(zhí)行補(bǔ)丁生成腳本,記錄代碼修改;
?歸檔內(nèi)容包含鏡像文件、編譯日志、內(nèi)核配置、Git提交清單,用于版本管理和問(wèn)題復(fù)現(xiàn)。
6.輔助邏輯(路徑/時(shí)間/日志)
?路徑格式化:STUB_PATH="$(echo $STUB_PATH | tr '[]' '[]')"將路徑轉(zhuǎn)為大寫,統(tǒng)一命名規(guī)范;
?時(shí)間戳:DATE=$(date +%Y%m%d.%H%M)生成時(shí)間戳,用于歸檔路徑和版本標(biāo)識(shí);
?日志輸出:大量echo "-------------------KERNEL_VERSION:$KERNEL_VERSION"輸出關(guān)鍵參數(shù),便于編譯過(guò)程調(diào)試。
三、腳本整體流程圖

四、掌握該腳本對(duì)開(kāi)發(fā)調(diào)試的意義
1.精準(zhǔn)控制編譯流程,提升開(kāi)發(fā)效率
?開(kāi)發(fā)階段無(wú)需全量編譯:調(diào)試UBoot時(shí)僅執(zhí)行./build.sh -U,調(diào)試內(nèi)核時(shí)執(zhí)行./build.sh -K,調(diào)試Android時(shí)執(zhí)行./build.sh -A,避免全量編譯耗時(shí)(RK3576全量編譯需1-2小時(shí));
?自定義編譯參數(shù):通過(guò)-J調(diào)整并發(fā)數(shù)(如低配機(jī)器執(zhí)行./build.sh -A -J 8),通過(guò)-v指定編譯版本(./build.sh -A -v user),適配不同調(diào)試場(chǎng)景。
2.快速定位編譯失敗點(diǎn)
?腳本每一步編譯后檢查$?并輸出日志,失敗時(shí)直接退出并打印原因(如“Build kernel failed!”);
?開(kāi)發(fā)者可根據(jù)日志定位失敗模塊:
?UBoot失敗:檢查UBOOT_DEFCONFIG是否正確、u-boot/make.sh是否有語(yǔ)法錯(cuò)誤;
?Kernel失敗:檢查KERNEL_DTS是否存在、Clang版本是否匹配、驅(qū)動(dòng)編譯依賴;
?Android失敗:檢查lunch命令是否正確、Android源碼是否完整。
3.定制化適配產(chǎn)品需求
?新增產(chǎn)品/版本:修改PRODUCT_KERNEL_DTS/PRODUCT_UBOOT_CONFIG等變量,或在參數(shù)解析分支中新增產(chǎn)品適配邏輯;
?定制固件打包:修改BUILD_PACKING邏輯,添加自定義歸檔內(nèi)容(如新增模塊的編譯產(chǎn)物);
?適配新編譯工具:調(diào)整Clang/JDK路徑,兼容新版編譯鏈(如升級(jí)Clang版本時(shí)修改clang-r530567為新路徑)。
4.理解RK平臺(tái)編譯體系,掌握量產(chǎn)固件制作
?腳本整合了瑞芯微定制工具([mkupdate.sh](mkupdate.sh)、[pack_resource.sh](pack_resource.sh))和Android原生編譯邏輯,是RK平臺(tái)“源碼→量產(chǎn)固件”的完整鏈路;
?掌握腳本后,可自主制作OTA包、update.img量產(chǎn)固件,適配工廠燒錄/用戶升級(jí)場(chǎng)景;
?歸檔邏輯(BUILD_PACKING)便于版本管理,調(diào)試時(shí)可追溯“某版本固件的編譯參數(shù)/代碼提交/內(nèi)核配置”,快速?gòu)?fù)現(xiàn)線上問(wèn)題。
5.適配AB分區(qū)/OTA升級(jí)等高級(jí)特性
?腳本區(qū)分AB分區(qū)(BOARD_USES_AB_IMAGE)和非AB分區(qū)的編譯邏輯,開(kāi)發(fā)者可通過(guò)腳本理解Android 15無(wú)縫更新(AB OTA)的實(shí)現(xiàn)方式;
?掌握OTA包生成流程,可定制升級(jí)腳本(如添加分區(qū)校驗(yàn)、預(yù)安裝腳本),滿足產(chǎn)品升級(jí)需求。
總結(jié)
該腳本是RK3576 Android 15平臺(tái)的“編譯總控中心”,涵蓋了從環(huán)境初始化到固件量產(chǎn)的全流程。開(kāi)發(fā)者掌握其邏輯,不僅能高效調(diào)試各模塊(UBoot/Kernel/Android),還能定制化適配產(chǎn)品需求,是RK3576平臺(tái)開(kāi)發(fā)調(diào)試的核心技能。同時(shí),腳本的模塊化設(shè)計(jì)、參數(shù)解析、錯(cuò)誤處理等Shell編程技巧,也為嵌入式Linux/Android開(kāi)發(fā)提供了通用參考。
審核編輯 黃宇
-
Android
+關(guān)注
關(guān)注
12文章
4024瀏覽量
133969 -
rk3576
+關(guān)注
關(guān)注
1文章
265瀏覽量
1546
發(fā)布評(píng)論請(qǐng)先 登錄
RK3576 Android15音頻開(kāi)發(fā)必看:alsa_route核心文件解析與修改場(chǎng)景
RK3576平臺(tái)Android HAL層故障排查:從lshal命令看透問(wèn)題本質(zhì)
深入解析RK平臺(tái)編譯核心:build.sh的知識(shí)點(diǎn)、調(diào)試技巧與開(kāi)發(fā)價(jià)值
硬核進(jìn)階:RK3576 Android15?驅(qū)動(dòng)與系統(tǒng)開(kāi)發(fā)實(shí)戰(zhàn)指南
迅為如何在RK3576上部署YOLOv5;基于RK3576構(gòu)建智能門禁系統(tǒng)
【作品合集】米爾RK3576開(kāi)發(fā)板測(cè)評(píng)
瑞芯微RK3576與RK3576S有什么區(qū)別,性能參數(shù)配置與型號(hào)差異解析
【米爾RK3576開(kāi)發(fā)板免費(fèi)體驗(yàn)】1、開(kāi)發(fā)環(huán)境、鏡像燒錄、QT開(kāi)發(fā)環(huán)境搭建以及應(yīng)用部署
RK這2款旗艦芯片RK3588 PK RK3576,誰(shuí)是最優(yōu)選
Mpp支持RK3576么
RK3576 vs RK3588:為何越來(lái)越多的開(kāi)發(fā)者轉(zhuǎn)向RK3576?
RK3576 Android 14.0 SDK開(kāi)發(fā)指南(第一集)
基于RK3576開(kāi)發(fā)板的QT GUI例程
基于RK3576開(kāi)發(fā)板的多路網(wǎng)絡(luò)攝像頭取流方案
RK3576 Android15?構(gòu)建腳本(build.sh)全解析
評(píng)論