多彩编程 多彩编程MZPH · CODE BLOG
ARTICLE DETAIL

文章详情

深耕前端与后端开发技术的一线实战笔记与踩坑复盘。

Ubuntu 20.04下RK3568开发板OpenHarmony 5.1全量编译实战指南

Ubuntu 20.04下RK3568开发板OpenHarmony 5.1全量编译实战指南 最近在Ubuntu 20.04上把RK3568对应的OpenHarmony 5.1完整编译跑通了从环境配置、源码拉取到最终拿到可烧录镜像整个过程踩了不少坑尤其是环境配置这一块的坑最隐蔽。这篇文章把我实际操作下来的完整流程、用到的命令、报错现场和解决办法全部记录下来目标很明确让第一次碰OpenHarmony编译的人少熬几个通宵。它适合两类人看一是刚接触OpenHarmony、准备在RK3568开发板上跑标准系统的同学二是搞过其他嵌入式Linux编译、但对OpenHarmony构建体系不熟悉的朋友。RK3568是目前OpenHarmony适配比较完善、社区资料也相对多的处理器平台从这里入手能少走不少弯路。1. 项目概述与基础认知1.1 编译的产物到底是什么先把概念理清楚。RK3568是一颗四核Cortex-A55处理器主频最高2.0GHz常见于各类开发板典型代表是润和的DAYU200以及瑞芯微官方EVB。OpenHarmony 5.1属于标准系统版本和轻量系统比如LiteOS-M那种跑在MCU上的完全是两码事它需要完整的Linux内核、根文件系统、系统服务、HAL层和图形栈所以构建产物体量非常大涉及到的组件数量也远超一般嵌入式Linux项目。编译完成后你最终会拿到一组固件核心包括引导加载程序u-boot、内核镜像boot、根文件系统镜像system.img、厂商分区vendor.img和升级镜像updater.img。烧到开发板上就是一个能跑起来的OpenHarmony标准系统。很多人一开始会把OpenHarmony的编译跟Android的编译弄混虽然入口都叫build.sh但OpenHarmony内部实际用的是hbHarmonyOS Build工具构建编排、依赖描述、产品配置逻辑都有一套自己的规则别用Android那套经验硬套。1.2 为什么锁死Ubuntu 20.04这是我最想强调的一点。OpenHarmony官方构建文档推荐的是Ubuntu 20.04.3及以上版本这个推荐不是随便写的。整个工具链里的预编译组件包括clang/llvm、各种host侧工具基本是按Ubuntu 20.04的glibc版本环境来编译的换到22.04或者24.04轻则某个.so加载失败重则编译到一半报出一堆看不懂的链接错误。我自己见过最典型的就是libssl.so.1.1: cannot open shared object file这种折腾半天后发现是系统版本导致的兼容问题。另外Ubuntu 20.04自带的Python 3.8.10正好落在OpenHarmony构建要求的3.8到3.11区间内省去折腾Python版本这一步。如果你机器上已经装好了22.04甚至更新版本也不是说完全编不了但你需要额外花大量时间处理兼容层从效率和成功率角度看直接上20.04是最省心的选择。2. 编译机环境准备与磁盘规划2.1 硬件配置和空间怎么算才够在动手之前先确认编译机的配置。我的实际建议是CPU至少8核16核以上编译体验会明显好内存16GB是下限但必须配合足够的swap32GB基本不用等磁盘是重中之重整个OpenHarmony 5.1全量源码拉下来大约25GB到30GB再加上编译中间产物out目录很容易飙到60GB以上我建议整机预留200GB空闲空间才比较从容。你可以用下面三条命令快速摸底nproc # 查看CPU核数 free -h # 查看内存和swap df -h # 查看磁盘剩余空间这里有个很实在的建议源码和编译产物尽量不要放在机械硬盘上也不要放在网络挂载盘里。OpenHarmony编译的随机IO非常密集NVMe固态和机械硬盘的编译时间差距能拉开一倍以上。如果条件允许单独准备一块SSD分区分给编译用体验会好很多。2.2 基础依赖包安装清单进入编译流程前先把系统基础依赖装齐。我整理了一份经过实操验证的安装命令sudo apt update sudo apt install -y git git-lfs curl wget unzip zip \ python3 python3-pip python3-venv \ build-essential binutils flex bison gperf \ libssl-dev libncurses5-dev libgl1-mesa-dev \ m4 bc ccache这些包每一件都有它存在的理由。git-lfs是必须装的OpenHarmony某些仓库用Git LFS管理大文件不装的话checkout阶段就会报错直接中断libssl-dev关系到后面签名、打包工具的正常运行ccache是一个编译缓存工具第一次全量编译时作用不明显但后续增量编译能省下大量时间。libncurses5-dev、libgl1-mesa-dev这类库主要服务于内核配置界面和图形相关组件的构建缺了会在特定模块报错。2.3 双系统、虚拟机与源码目录选择我在实际编译时用的是双系统方式安装的Ubuntu 20.04独立分区直通硬件资源编译过程中内存和磁盘IO都不会有虚拟化损耗。如果你打算用虚拟机几个注意事项虚拟磁盘最好用固定大小而不是动态扩展动态扩展在长时间高负载写入时性能下降很明显内存分配宁多勿少千万不要只给4GB否则构建跑到一半进程被OOM killer干掉那种挫败感真的很劝退。源码目录建议放在一个足够大的独立分区下别跟系统根分区混在一起。比如你的Ubuntu 20.04系统盘只有100GB但另外挂载了一个500GB的数据盘那就把源码放数据盘里。还有一个小技巧把编译输出的out目录做成软链接指向另一块空间更大的磁盘这样即使系统盘空间紧张也不会因为out目录膨胀而报No space left on device。命令很简单ln -s /data/ohos_build_out /home/yourname/ohos/out3. 源码拉取repo、manifest与版本锁定3.1 repo工具安装与manifest初始化OpenHarmony的源码量非常大官方用repo工具来管理这种多仓库项目。先把repo工具装好mkdir -p ~/bin curl https://storage.googleapis.com/git-repo-downloads/repo -o ~/bin/repo chmod x ~/bin/repo export PATH~/bin:$PATH如果默认下载源不太稳定可以找gitee上的repo镜像代替思路是一样的。装好之后开始拉取OpenHarmony 5.1的源码mkdir -p ~/ohos cd ~/ohos repo init -u https://gitee.com/openharmony/manifest.git -b OpenHarmony-5.1.0-Release repo sync -c这里-c参数表示只同步当前分支的最新代码不做全历史同步能省下大量下载时间和磁盘空间。如果你网络状况不理想repo sync -c中断了也没关系重复执行同一条命令即可repo支持断点续传会从上次中断的地方继续拉取。3.2 同步结束后的LFS与大文件校验源码同步完成后不要急着进编译先执行一次LFS文件校验。很多第一次拉代码的人会在这里踩坑明明repo sync显示成功但编译到某个组件时莫名其妙报文件缺失或者解压失败大概率就是LFS大文件没拉全。git lfs pull这条命令会遍历所有仓库把Git LFS跟踪的大文件真正下载到本地。它的耗时取决于网络状况但这一步省不了。我实测过跳过这一步直接编译跑到图形栈相关组件时必挂报错信息又非常隐晦排查起来特别费时间。3.3 版本锁定为什么不能乱动OpenHarmony的manifest仓库非常关键。每个发布版本manifest文件都会把几百个子仓库锁定到唯一的提交ID上包括工具链版本、SDK版本、组件依赖关系全被锁死。这也是为什么同一个版本号的源代码在不同时间点拉取编译出来的结果可能有细微差异。不要手动去切换某个子仓库的分支或提交我身边有同事为了“试试新特性”手动checkout了某个组件的新分支结果编译虽然过了但系统跑起来各种崩溃最后排查半天还是得回到manifest锁定的版本。做系统级构建一定要记住先按官方锁定的环境跑通全流程再谈定制修改这个顺序不能乱。4. 工具链配置Python、Node.js与hb4.1 Python版本检查与Node.js替换OpenHarmony 5.x的构建脚本依赖Python 3.8到3.11Ubuntu 20.04自带的Python 3.8.10正好满足要求所以Python这一关基本不用动。真正麻烦的是Node.js。构建过程中打包、编译JS框架、生成hap包这些环节都需要Node.js官方要求版本14.19.1及以上而Ubuntu 20.04的apt源里默认的nodejs版本是10.x直接装的话编译到JS相关任务时会报语法错误。正确做法是下载官方Node.js二进制包我实际用的是v16.20.2稳定可靠cd /usr/local sudo tar -xJf node-v16.20.2-linux-x64.tar.xz然后在~/.bashrc里追加环境变量export PATH/usr/local/node-v16.20.2-linux-x64/bin:$PATH执行source ~/.bashrc后验证node -v npm -v顺便可以给npm换一个国内镜像源后面安装依赖会快很多npm config set registry https://registry.npmmirror.com4.2 hb构建工具安装与产品选择hb工具不是通过apt安装的而是直接从源码里安装。进入源码根目录后执行python3 -m pip install --user build/hb安装完如果提示找不到hb命令检查一下~/.local/bin是否在PATH里export PATH$PATH:~/.local/bin接下来是关键一步选择编译产品。hb set执行后会出现一个交互式列表在标准系统分类下找到rk3568选中确认。如果不想用交互界面也可以直接指定hb set -p rk3568每次打开新终端开始编译前我强烈建议先执行hb env看一眼当前配置。这个工具不像Android编译那样会自动检测目录一旦工作目录或者产品配置被重置成默认值编译出来的东西可能根本不是你要的。5. RK3568全量编译实操记录5.1 编译命令、参数与首次耗时环境配置完毕开始正式编译。第一次全量编译建议直接用根目录下的build.sh入口./build.sh --product-name rk3568 --ccache--ccache参数用来开启编译缓存第一次编译时它没有太大作用但后续改代码再编译时能节省大量时间。编译启动后会先做依赖检查、创建构建目录、解析产品配置这个过程本身就要几分钟看起来像卡住了其实是在干活。在我这台16核32GB内存的机器上第一次全量编译跑了大约一个半小时到两个小时。如果你的机器是8核16GB做好3小时以上的心理准备。编译过程中CPU会长时间保持满负载风扇声音会很大这是正常现象。如果编译过程中某个组件报错退出不要直接重新跑全量命令先把日志翻出来确认问题具体排查思路我放在第6章。5.2 编译产物位置与烧录前的检查编译完成后产物集中在out/rk3568/packages/phone/images/我整理了一下主要文件和它们的作用文件名作用boot_linux.img内核镜像包含Linux内核和ramdisksystem.img系统分区包含系统基础服务和框架vendor.img厂商分区包含设备HAL和专属配置updater.img升级镜像用于OTA或本地升级u-boot.img引导加载程序一般在uboot输出目录下烧录时我用的是瑞芯微官方的RKDevTool按分区表把对应镜像填进去就行。这里有个经验首次拿到开发板先烧一份官方参考固件验证硬件没问题再烧自己编译的镜像。否则硬件有问题时你会误以为是自己的编译问题排查方向就偏了。5.3 后续修改设备树、内核和模块的单编编译跑通之后你大概率会面临修改设备树、调整内核配置这类需求。典型的例子是开发板默认屏幕是竖屏但应用需要横屏显示这就要改设备树。在OpenHarmony的构建体系里这类修改不需要每次都全量编译。改完设备树后可以只重新编内核和资源镜像然后重新打包升级镜像烧录验证即可。对应的构建命令是hb build -T指定目标组件但注意不要绕过完整打包流程否则系统分区和vendor分区版本不匹配烧进去会出一些很奇怪的运行问题。我自己的习惯是小改动就用增量编译改动范围涉及多个子系统时干脆老老实实重新全量编译一次省得排查问题时分不清是代码问题还是混编带来的脏数据问题。6. 高频问题与排查技巧实录6.1 问题速查表把这次实操中遇到的典型问题整理成速查表遇到类似报错可以对照排查症状根本原因解决办法hb: command not foundPATH未包含pip安装目录export PATH$PATH:~/.local/bin编译中断并提示No space left on deviceout目录所在分区空间不足清理out旧产物或把out软链接到更大分区JS框架编译阶段报node相关错误Node.js版本过低用官方Node.js v16替换apt版本libssl.so.1.1相关报错系统版本高于Ubuntu 20.04切换20.04或手动安装兼容libsslrepo sync过程中LFS文件报错git-lfs未安装或未初始化apt install git-lfs git lfs install编译中途进程被OOM killer干掉内存不足增加swap或减少并发任务数某个third_party组件反复失败源码或LFS文件未同步完整重新repo sync -c并执行git lfs pullPython相关脚本异常Python版本不匹配确认python3版本在3.8到3.11之间6.2 定位失败现场的两个关键日志编译失败时第一时间不要盲目重试先看日志。build.sh执行过程中如果输出不完整完整的构建日志在out/rk3568/build.log通过这个日志能看到具体是哪个组件失败了。查看日志末尾tail -50 out/rk3568/build.log定位到失败组件后可以只重编这个目标不用全量重新来hb build -T target_nametarget_name对应失败的那个构建任务名比如某个inner_kits或者可执行文件目标。如果日志反复在同一个组件上失败看一下是不是编译缓存有问题把out/rk3568下对应的子目录删掉再重编有时候能解决问题。但不要轻易删整个out目录删一次就意味着一轮全量编译时间成本太高。6.3 二次编译、缓存与提速心得编译过一次之后后续的增量编译速度会快很多但有几个习惯能帮你进一步压缩时间。第一个是坚持开启--ccache。ccache的缓存目录默认在~/.cache/ccache不要频繁清理它。实测同样的平台开缓存后二次全量编译能省30%左右的时间如果只是改了一两个组件速度提升更明显。第二个是能增量就增量。只改设备树或者内核配置不要动不动就全量编译用hb build -T指定目标就行。但改动范围跨多个子系统时我还是建议老老实实全量重编避免增量混编带来的版本一致性问题。第三个是编译时尽量关掉图形界面和浏览器这类内存大户。ninja会按照机器可用内存动态调整并发任务数内存越充裕并行度越高编译就越快。我曾经一边开浏览器查资料一边编译结果编译时间比安静环境下长了不少后来就学乖了编译期间专心干点别的事别在编译机上折腾其他重负载操作。这次把RK3568的OpenHarmony 5.1全流程编译跑下来我最深的体会是OpenHarmony的构建体系并没有想象中那么神秘真正吃时间的不是编译本身而是环境配置和版本匹配。如果有人问我第一步该做什么我一定会说先花半小时把磁盘空间、内存swap、Node.js版本和hb环境全部确认一遍再启动编译。这能让你少熬好几个小时的夜。另外无论是做驱动适配还是应用移植都建议先保持系统镜像原样跑通基础功能再逐步加入自己的改动这种节奏能最大程度避免方向性问题。希望这篇记录能帮你顺利跑通第一次编译。
返回列表