02_代码编译、构建、烧录和测试
山东大学 2023 级软件工程创新实训项目博客。
上一篇完成了环境、源码结构和基础知识准备。这一阶段的目标,是把“看得懂一些源码”推进到真正可执行的工程闭环:
获取源码 → 准备预编译工具 → 全量构建 → 生成镜像 → 烧录设备 → 建立测试基线
这条链路一旦跑通,后面每一项外设修改才有可靠落点。否则代码即使改对了,也可能没有被编译、没有进入镜像,或者烧录后无法判断到底使用的是新产物还是旧文件。
获取 OpenHarmony 6.1 RISC-V 源码
OpenHarmony 由大量 Git 仓库组成,因此使用 repo 管理清单和同步过程。当前项目使用进迭时空/如意社区提供的 OpenHarmony 6.1 RISC-V 分支。
初始化示例:
repo init \
-u https://code.openruyi.cn/risc-verse/ruyi-desktop-os/manifest.git \
-b OpenHarmony-v6.1-Release-RISC-V \
--no-repo-verify
同步源码:
repo sync -c -j4 --retry-fetches=100 --fail-fast
repo forall -c 'git lfs pull'
这里最容易忽略的是:repo sync 命令结束,不一定等于所有仓库和 Git LFS 大文件都完整。后续出现头文件、二进制或模型文件缺失时,应该先核对对应子仓库状态,而不是立刻在代码中“造一个文件”绕过错误。
如果某个子仓库同步不完整,可以进入该目录单独检查远端、分支和 LFS:
git status
git remote -v
git branch -a
git lfs pull
项目初期确实遇到过仓库访问方式、令牌权限和个别子仓库不完整的问题。最终改用可访问的 HTTPS manifest,并针对缺失仓库重新同步,才得到可持续构建的源码树。
安装依赖与预编译工具
MUSEPaper2 的板级说明给出了 Ubuntu 22.04 所需的软件包,包括编译器基础工具、Java、Python、Node.js、文件系统工具、设备树工具和 ccache 等。
安装系统依赖后,还需要在源码根目录下载 OpenHarmony 的预编译工具:
bash build/prebuilts_download.sh
预编译目录中包含 Clang/LLVM、GN、Ninja、Node.js 以及构建脚本依赖的其他二进制工具。它们与源码分支需要匹配,因此不建议随意使用系统里另一个版本的工具替代。
第一次全量构建
进入源码根目录,执行 MUSEPaper2 产品构建:
./build.sh \
--product-name musepaper2 \
--ccache \
--no-prebuilt-sdk
参数含义:
--product-name musepaper2:选择 MUSEPaper2 产品配置;--ccache:启用编译缓存,后续增量构建速度会明显提高;--no-prebuilt-sdk:从当前源码构建所需 SDK,而不是完全依赖预置 SDK。
构建过程并不是简单地把所有 .cpp 文件编译一遍。它大致经历:
- 解析产品与部件配置;
- GN 生成 Ninja 构建图;
- Ninja 编译内核、系统部件、HDF/HDI、应用和工具;
- 把模块安装到 system、vendor 等临时目录;
- 生成各分区镜像和安装清单;
- 执行依赖、权限、SELinux、NOTICE 等检查。
因此报错时不能只看一行 FAILED,还要确认失败发生在哪个阶段。
初期遇到的典型问题
1. 子仓库内容不完整
构建曾出现类似错误:
fatal error: 'v1_1/display_composer_type.h' file not found
fatal error: cannot find include path for ...
这类问题首先应该确认目标文件本应由哪个仓库提供,再检查该仓库是否同步完整。对于 Git LFS 管理的文件,还要执行 git lfs pull。
2. 头文件依赖没有显式声明
也遇到过:
error: 'uint32_t' has not been declared
error: unknown type name 'uint32_t'
这种问题可以通过补充标准头文件解决,但不能只满足于“加一行以后能编译”。还需要确认这是源码缺少显式依赖、工具链差异,还是前一个头文件未正确同步造成的连锁错误,并记录修改原因,避免留下无法解释的临时补丁。
3. 内存不足与 OOM
完整构建持续时间长、并行任务多,16 GB 内存环境可能触发 OOM。典型表现是编译进程或整个桌面会话突然退出,但构建日志中没有直观的语法错误。
可以通过以下命令检查:
free -h
dmesg | grep -i -E "oom|killed process"
解决思路包括降低并行度、启用足够的 swap,以及在编译期间避免同时运行高内存应用。
4. 磁盘空间不足
源码、预编译工具、Git 对象和 out 目录会占用大量空间。扩大 swap 时也不能忘记它同样占用磁盘。如果根分区被写满,除了构建失败,图形界面和系统服务也可能无法启动。
df -h
du -sh out
du -sh .repo
这次经历让我意识到,嵌入式系统构建中的“环境问题”并不比代码问题简单。稳定、可复现的主机环境本身就是项目基础设施的一部分。
构建产物在哪里
编译完成后,主要输出位于:
out/musepaper2/
用于烧录的镜像位于:
out/musepaper2/packages/phone/images/
其中可能包含:
boot.img
system.img
vendor.img
userdata.img
updater.img
fastboot.yaml
不同镜像承担的内容不同:
boot.img:内核和启动相关内容;system.img:OpenHarmony Framework、系统服务和系统应用;vendor.img:板级服务、外设配置、vendor 库和固件;userdata.img:用户数据分区初始内容。
这也是后续定位“修改应该进入哪个分区”的依据。例如板级蓝牙固件和 Wi-Fi 配置通常进入 vendor,而 Camera 应用会进入 system。
生成完整烧录包
镜像构建完成后,使用板级脚本生成完整烧录包:
./build/gen_zip.sh musepaper2
输出文件为:
out/musepaper2/packages/phone/images/
openharmony-spacemit-musepaper2.zip
在后期完成全部适配后,最终一次全量构建通过了 4289/4289 个 Ninja 步骤,并成功生成上述 ZIP。这说明摄像头、Wi-Fi、USB 和蓝牙相关的 GN 依赖已经能够同时通过全量构建。
不过,“编译成功”只说明构建图可以执行完,并不能单独证明每项功能正确。还要检查关键文件是否进入打包目录,例如:
vendor/etc/wifi/wpa_supplicant.conf
vendor/bin/wifi_fix.sh
vendor/etc/firmware/rtl8852bs_fw
vendor/etc/firmware/rtl8852bs_config
system/app/com.ohos.camera/Camera.hap
对于重要产物,还应该保存哈希:
sha256sum openharmony-spacemit-musepaper2.zip
sha256sum boot.img system.img vendor.img
这样才能确认设备端或团队成员之间使用的是同一个版本。
烧录时的原则
初期我们首先将原始系统版本烧录到设备,用于建立功能基线。烧录应优先使用进迭时空提供的官方工具和完整烧录配置,不应在不了解分区布局时随意写入启动分区。
需要特别区分:
- 完整烧录:适合验证一套镜像能否在新设备上完整复现;
- 增量部署:适合缩短开发周期,例如通过 HDC 临时替换某个 HAP 或共享库;
- 单分区写入:风险高于普通文件替换,必须核对实际启动介质、分区名和镜像尺寸;
- boot/env/分区表操作:可能直接导致设备无法启动,必须先备份并保存哈希。
开发阶段可以用增量部署验证修改方向,但最终结果必须回到源码和完整构建关系。否则设备上虽然暂时可用,重新烧录后修改就会消失。
原始系统测试结果
原始系统烧录并启动后,我们按照统一清单逐项检查。
系统与 HDC
- 系统可以进入桌面;
- HDC 可以连接设备;
- 静置或电源状态变化后,HDC 存在掉线风险。
后续定位表明,USB PHY 会受到系统深度休眠策略影响,因此 USB/HDC 稳定性被列为独立任务。
Wi-Fi
- 硬件使用 RTL8852BS;
- Wi-Fi 数据链路走 SDIO;
- 原始系统中的驱动、供电和
wpa_supplicant启动流程仍需完善。
后续工作补齐了 8852bs.ko、Wi-Fi 运行目录、配置文件、启动服务和休眠供电处理。
摄像头
- 底层能够看到部分视频设备;
- 前后摄映射、格式能力、预览和拍照链路不完整;
- Camera App 还不能形成“预览—切换—拍照—相册保存”的稳定闭环。
这成为我后续首先负责的外设适配任务。
蓝牙
- 设置中存在蓝牙开关,系统也包含蓝牙服务;
- 但 HCI 初始化和扫描不能稳定完成;
- 后续需要继续检查 UART、rfkill、Realtek vendor、firmware 和 HCI HDI。
其他基础能力
显示、触控和系统基础界面可以工作,为继续进行外设适配提供了可用环境。
测试不能只看界面
设置页出现开关,最多只能证明上层 UI 和部分系统服务存在。真正验证外设需要跨层证据。
例如 Wi-Fi 可以检查:
lsmod | grep 8852
ip link show wlan0
ps -A | grep wpa_supplicant
蓝牙可以检查:
ls -l /dev/ttyS2
cat /sys/class/rfkill/rfkill0/state
ps -A | grep -E "blue_host|bluetooth_service"
USB/HDC 可以检查:
param get sys.usb.config
ps -A | grep hdcd
hdc list targets
摄像头可以检查:
ls -l /dev/video*
hilog | grep -i -E "camera|v4l2"
我们逐渐把验证标准从“界面看起来能点”改成:
硬件节点存在
+ 驱动/服务稳定
+ 日志链路正确
+ 用户功能可完成
+ 重启后仍然有效
阶段结论
完成这一阶段后,我们得到的不只是一次编译结果,而是一套后续适配可以反复使用的闭环:
- 源码能够同步并处理 Git LFS;
- MUSEPaper2 产品能够完成全量构建;
- 能够生成分区镜像和完整 ZIP;
- 原始系统已经烧录并完成外设基线测试;
- USB、Wi-Fi、摄像头和蓝牙的问题边界初步明确;
- 后续修改需要经过“单项验证—源码集成—全量构建—冷启动回归”。
这一步跑通后,项目才真正从准备阶段进入外设适配阶段。后续文章会分别记录 OpenHarmony 6.1 源码学习、官方构建问题、摄像头和蓝牙的完整适配过程。
更多推荐
所有评论(0)