欢迎加入开源鸿蒙PC社区:https://harmonypc.csdn.net/
欢迎在PC社区平台申请新建项目:https://atomgit.com/OpenHarmonyPCDeveloper
摘要
这篇文章记录了我在鸿蒙 PC(HarmonyOS 5.1.1 / API 19)上从零搭建 HarmonyPCDemo 工程时,遭遇 hvigor 构建链连续三轮阻断的完整复盘。从 modelVersion 版本号不兼容,到 app.json5 schema 字段非法,再到 ArkTS 严格模式下的编译 ERROR,总计跨越 6 个配置文件、10 行代码改动、耗时约两小时。如果你刚刚从 DevEco Studio 创建好一个鸿蒙 PC 空工程、正准备点 Build 按钮,这篇文章可以帮你跳过所有我踩过的坑------直接用一份 checklist 把构建打通。所有报错原文、文件路径、修复代码都真实可复现,仓库源码在文章末尾的 AtomGit 链接中公开。
目录
- 摘要
- [适用读者 / 前置知识 / 涉及工具版本](#适用读者 / 前置知识 / 涉及工具版本)
- 踩坑故事(按时间顺序)
- 准备工作
- [第一轮:modelVersion 6.1.1 不被 hvigor 6.0.0 支持](#第一轮:modelVersion 6.1.1 不被 hvigor 6.0.0 支持)
- [第二轮:schema 校验 buildVersion 非法](#第二轮:schema 校验 buildVersion 非法)
- [第三轮:ArkTS 的 compilation ERROR](#第三轮:ArkTS 的 compilation ERROR)
- 构建成功日志
- 三条通用经验总结
- [经验 1:先把所有 modelVersion 统一到最低兼容版本](#经验 1:先把所有 modelVersion 统一到最低兼容版本)
- [经验 2:API 升级时重点检查 JSON5 schema 的字段去留](#经验 2:API 升级时重点检查 JSON5 schema 的字段去留)
- [经验 3:ArkTS 严格模式是"善意的麻烦",不要关闭它](#经验 3:ArkTS 严格模式是"善意的麻烦",不要关闭它)
- [AtomGit 仓库链接 & 赛道二 PR](#AtomGit 仓库链接 & 赛道二 PR)
- [🔓 赛道二积分赛配套 PR(path A:三方库适配)](#🔓 赛道二积分赛配套 PR(path A:三方库适配))
- [配方结构:10 个文件各司其职](#配方结构:10 个文件各司其职)
- conanfile.py:从取源到签名的完整链路
- 为什么禁用全部音频后端
- 代码审查:一次很有价值的「打回」
- 这次打回教给我的三件事
- 作者声明
适用读者 / 前置知识 / 涉及工具版本
适用读者:第一次接触鸿蒙 PC 开发的同学、从 HarmonyOS 手机端迁移到 PC 端的开发者、尝试用 DevEco Studio 6.0 搭建 API 19 工程但构建不过的新手。
前置知识:了解 JSON5 配置文件的基本语法、知道 hvigor 是鸿蒙的构建工具(类似 Android 的 Gradle / Web 的 Vite)、能在 DevEco Studio 里打开项目并找到 Build 按钮即可。不需要任何鸿蒙开发经验。
涉及工具和版本(这个版本号非常重要,鸿蒙工具链更新极快,版本对不上报错可能完全不一样):
| 组件 | 版本 |
|---|---|
| DevEco Studio | 6.0(Build 6.0.1.100) |
| hvigor | 6.0.0 |
| OpenHarmony SDK / API | 5.1.1 (API 19) |
| 操作系统 | Windows 11 |
| Node.js | v18+ |
踩坑故事(按时间顺序)
下面这张流程图把整条踩坑链路串了起来,红色节点是三次构建失败的位置。你可以按图索骥:先看自己卡在哪一个红色节点,再直接跳到对应小节看报错原文和修复方案,不必从头读。
#mermaid-svg-FCcxCDOiCotCxcC6{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-FCcxCDOiCotCxcC6 .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-FCcxCDOiCotCxcC6 .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-FCcxCDOiCotCxcC6 .error-icon{fill:#552222;}#mermaid-svg-FCcxCDOiCotCxcC6 .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-FCcxCDOiCotCxcC6 .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-FCcxCDOiCotCxcC6 .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-FCcxCDOiCotCxcC6 .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-FCcxCDOiCotCxcC6 .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-FCcxCDOiCotCxcC6 .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-FCcxCDOiCotCxcC6 .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-FCcxCDOiCotCxcC6 .marker{fill:#333333;stroke:#333333;}#mermaid-svg-FCcxCDOiCotCxcC6 .marker.cross{stroke:#333333;}#mermaid-svg-FCcxCDOiCotCxcC6 svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-FCcxCDOiCotCxcC6 p{margin:0;}#mermaid-svg-FCcxCDOiCotCxcC6 .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-FCcxCDOiCotCxcC6 .cluster-label text{fill:#333;}#mermaid-svg-FCcxCDOiCotCxcC6 .cluster-label span{color:#333;}#mermaid-svg-FCcxCDOiCotCxcC6 .cluster-label span p{background-color:transparent;}#mermaid-svg-FCcxCDOiCotCxcC6 .label text,#mermaid-svg-FCcxCDOiCotCxcC6 span{fill:#333;color:#333;}#mermaid-svg-FCcxCDOiCotCxcC6 .node rect,#mermaid-svg-FCcxCDOiCotCxcC6 .node circle,#mermaid-svg-FCcxCDOiCotCxcC6 .node ellipse,#mermaid-svg-FCcxCDOiCotCxcC6 .node polygon,#mermaid-svg-FCcxCDOiCotCxcC6 .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-FCcxCDOiCotCxcC6 .rough-node .label text,#mermaid-svg-FCcxCDOiCotCxcC6 .node .label text,#mermaid-svg-FCcxCDOiCotCxcC6 .image-shape .label,#mermaid-svg-FCcxCDOiCotCxcC6 .icon-shape .label{text-anchor:middle;}#mermaid-svg-FCcxCDOiCotCxcC6 .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-FCcxCDOiCotCxcC6 .rough-node .label,#mermaid-svg-FCcxCDOiCotCxcC6 .node .label,#mermaid-svg-FCcxCDOiCotCxcC6 .image-shape .label,#mermaid-svg-FCcxCDOiCotCxcC6 .icon-shape .label{text-align:center;}#mermaid-svg-FCcxCDOiCotCxcC6 .node.clickable{cursor:pointer;}#mermaid-svg-FCcxCDOiCotCxcC6 .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-FCcxCDOiCotCxcC6 .arrowheadPath{fill:#333333;}#mermaid-svg-FCcxCDOiCotCxcC6 .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-FCcxCDOiCotCxcC6 .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-FCcxCDOiCotCxcC6 .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-FCcxCDOiCotCxcC6 .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-FCcxCDOiCotCxcC6 .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-FCcxCDOiCotCxcC6 .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-FCcxCDOiCotCxcC6 .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-FCcxCDOiCotCxcC6 .cluster text{fill:#333;}#mermaid-svg-FCcxCDOiCotCxcC6 .cluster span{color:#333;}#mermaid-svg-FCcxCDOiCotCxcC6 div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-FCcxCDOiCotCxcC6 .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-FCcxCDOiCotCxcC6 rect.text{fill:none;stroke-width:0;}#mermaid-svg-FCcxCDOiCotCxcC6 .icon-shape,#mermaid-svg-FCcxCDOiCotCxcC6 .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-FCcxCDOiCotCxcC6 .icon-shape p,#mermaid-svg-FCcxCDOiCotCxcC6 .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-FCcxCDOiCotCxcC6 .icon-shape .label rect,#mermaid-svg-FCcxCDOiCotCxcC6 .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-FCcxCDOiCotCxcC6 .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-FCcxCDOiCotCxcC6 .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-FCcxCDOiCotCxcC6 :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 创建工程(Empty Ability 向导)
Sync 失败:modelVersion 6.1.1 不被支持
改 4 个文件的 modelVersion 为 6.0.0
Build 失败:schema 校验 buildVersion 非法
删除 app.json5 中的 buildVersion
CompileArkTS 报 5 个 ERROR
修复 ArkTS 严格模式问题
BUILD SUCCESSFUL
准备工作
我在 DevEco Studio 里走了一遍"Create Project → Application → HarmonyOS PC → Empty Ability"的向导,IDE 自动给我生成了一个带 entry 模块的 stage 模型工程。

向导默认勾选了"自动同步 Gradle/Hvigor",所以工程一落地 hvigor 就开始跑配置。我等它跑完,看到右下角显示"Sync finished with errors",点开报错面板------好,第一轮坑来了。
第一轮:modelVersion 6.1.1 不被 hvigor 6.0.0 支持
现象:hvigor 在加载项目配置阶段直接报错,构建流程根本还没开始编译 ArkTS 就已经挂了。报错内容非常明确:hvigor 声明它是 6.0.0 版本,但工程里的配置文件写的是 6.1.1,它不认。
报错原文 (来自 .hvigor/outputs/build-logs/build.log 中 2026-09-24 那几次构建的 DEBUG 输出):

[DEBUG] debug-file - env: hvigor-config.json5 content = {
modelVersion: '6.1.1',
dependencies: {},
execution: {},
logging: {},
debugging: {},
nodeOptions: {}
}
...
Error: Unsupported modelVersion '6.1.1' in hvigor-config.json5.
The current hvigor plugin version only supports modelVersion up to '6.0.0'.
根因分析 :DevEco Studio 的向导模板有 bug------它给新建工程生成的 modelVersion 是 6.1.1,但随 DevEco Studio 6.0 打包的 hvigor-ohos-plugin 实际支持的最高版本是 6.0.0。这个版本号不是随便写的,hvigor 内部有硬编码的版本校验,读配置时比对失败就直接抛异常退出。换句话说,IDE 自己生成了一个自己不认识的配置。
修复方案 :把所有 modelVersion 字段从 "6.1.1" 统一改成 "6.0.0"。我项目里有一份根工程 + 一个 demo 子目录,所以总共是 4 个文件需要修改:
| # | 文件路径 | 改动 |
|---|---|---|
| 1 | hvigor/hvigor-config.json5 |
"modelVersion": "6.1.1" → "modelVersion": "6.0.0" |
| 2 | oh-package.json5 |
"modelVersion": "6.1.1" → "modelVersion": "6.0.0" |
| 3 | demo/hvigor/hvigor-config.json5 |
同上 |
| 4 | demo/oh-package.json5 |
同上 |
修改后的 hvigor/hvigor-config.json5 关键部分长这样:
typescript
{
"modelVersion": "6.0.0",
"dependencies": {},
"execution": {
// "daemon": true,
},
// ...其余字段保持原样
}
修改完这 4 个文件,Ctrl+S 保存,DevEco Studio 右下角的小锤子图标闪了一下------这一次 Sync 成功了。控制台没有再抛 modelVersion 异常。我松了一口气,点了 Build Hap。几秒后,第二轮报错刷了出来。
第二轮:schema 校验 buildVersion 非法
现象 :这一次错误来得比上一轮快,而且不是在配置加载阶段,而是在 ProcessProfile 任务里。hvigor 会用内置的 JSON Schema 去校验 app.json5 和 module.json5,结果 Schema 里没有了 buildVersion 这个字段定义,但我的文件里还留着它,所以校验器直接拒绝了。
报错原文(来自 DevEco Studio Build 面板的红色 Error):
ERROR: Schema validation failed for AppScope/app.json5 at path '#/app/buildVersion':
keyword: additionalProperties, message: additional property 'buildVersion' not allowed.
schema: https://developer.huawei.com/consumer/cn/doc/harmonyos-references-V5/app-json5-schema-V5
根因分析 :从 API 12 左右开始,鸿蒙对 app.json5 做了 schema 收缩------app 对象里原来的 buildVersion、buildOption 这些字段被移除了,拆到了 build-profile.json5 的 products[].buildOption 下面。但如果你是从一个老工程模板拷过来的,或者 DevEco Studio 6.0 的向导还是生成了带 buildVersion 的旧格式(对,这就是我遇到的情况),schema 校验就会卡你。
修复方案 :打开每个 AppScope/app.json5,找到 app 对象里的 buildVersion 字段,删掉它。我有两份 app.json5,所以是两个文件:
| # | 文件路径 | 操作 |
|---|---|---|
| 1 | AppScope/app.json5 |
删除 "buildVersion": "x.y.z" 那一行 |
| 2 | demo/AppScope/app.json5 |
同上 |
修复前 的 AppScope/app.json5(示意):
typescript
{
"app": {
"bundleName": "com.example.demo2",
"vendor": "example",
"versionCode": 1000000,
"versionName": "1.0.0",
"buildVersion": "5.0.0", // ← 就是这行,删掉
"icon": "$media:layered_image",
"label": "$string:app_name"
}
}
修复后 的 AppScope/app.json5(当前仓库版本):
typescript
{
"app": {
"bundleName": "com.example.demo2",
"vendor": "example",
"versionCode": 1000000,
"versionName": "1.0.0",
"icon": "$media:layered_image",
"label": "$string:app_name"
}
}
注意:versionCode 和 versionName 是保留的,只有 buildVersion 要删。别删错了。再次点 Build,schema 错误消失了,ArkTS 编译任务开始跑------然后第三轮 ERROR 炸了出来,这一轮是 5 个 ArkTS 编译错误,颜色从"红色阻断"变成了"5 个 ERROR 汇总"。
第三轮:ArkTS的 compilation ERROR
现象 :hvigor 已经走到了 CompileArkTS 阶段,Ark 编译器逐个编译 entry 模块里的 10 个 .ets 文件,然后统一在控制台打印了 多 个 ERROR。

严格模式对新手来说不友好,但长远来看是好事------它能在编译期就把这些隐患抓出来,比到 runtime crash 强多了。由于篇幅有限,这 5 个 ERROR 的每一个具体代码定位、改前改后对比、严格模式背后的设计意图,我打算单独写一篇文章来讲,这里先跳过细节。
构建成功日志
三轮坑全部填平之后,终于迎来了第一次完整成功构建。以下是 DevEco Studio Build 面板里摘出来的关键输出(时间戳和实际行数略有裁剪,内容 100% 真实):

看到最后那行绿色的 BUILD SUCCESSFUL 的时候,我截了个图。从打开 DevEco Studio 的 Create Project 向导到真正产出可部署的 .hap,我踩了 3 轮坑、改了 6 个文件、查了 2 小时华为开发者文档。现在写下来,希望下一个同学能省点时间。

本项目代码运行演示效果如下:


从 openEuler 三方库中选一个适配到 HarmonyOS PC 主线框架。我选了 libsoundio 2.0.0 ------它是一个跨平台音频 I/O 库,纯 C 实现、单头文件、CMake 构建,支持 JACK / PulseAudio / ALSA / CoreAudio / WASAPI 等主流音频后端。之所以选它而不是更简单的库(比如 xxhash、lz4),一是 soundio 作为音频基础设施,适配难度适中(需要处理 OHOS 暂无音频后端的降级策略),二是它在鸿蒙 PC 场景下有实际价值------未来跨平台音频应用都需要类似的 low-level I/O 能力。
适配成果通过 SoundioDemo 页面可视化展示------Home 首页按钮 ② 点进去可以看到:顶部 soundio 版本号大卡片、7 种音频后端列表(dummy 启用 ✅,其余 6 种禁用 ❌,和 PR #19174 的 CMake 选项一一对应)、音频设备枚举(麦克风 🎤 / 扬声器 🔊)。页面通过soundio_bridge.ets → NAPIsoundio_napi.cpp →libsoundio.so 三层调用链对接 PR 构建产物,Windows 预览器下走 mock fallback,真机上用真实 .so。这条链路验证了 "Conan 配方适配 → NAPI 封装 → ArkTS UI" 三方库集成的完整模式,对后续适配其他 C/C++ 库有参考价值。
三条通用经验总结
经验 1:先把所有 modelVersion 统一到最低兼容版本
鸿蒙的 hvigor 对版本号极度敏感。DevEco Studio 向导可能给你生成一个比实际 hvigor 插件更高的 modelVersion(我遇到的是 6.1.1 vs 6.0.0),而且这个字段在每个 hvigor-config.json5 和每个 oh-package.json5 里都要写,只要有一个文件版本号不匹配就卡壳。我的做法是:在向导刚建完工程、什么代码都没写之前,全局搜索所有 modelVersion,把它们全部改成 6.0.0(或者你实际安装的 hvigor 版本)。这样做能省掉至少半小时的排错时间。
经验 2:API 升级时重点检查 JSON5 schema 的字段去留
鸿蒙每次 API 大版本升级都会做 schema 收缩------旧字段被移除、新字段被加进来、字段从 A 文件搬到 B 文件。buildVersion 从 app.json5 搬到 build-profile.json5 是一个典型例子。如果你看到 additional property 'xxx' not allowed 这样的报错,99% 概率是你文件里残留了旧 schema 里的字段。最快的定位方式是打开 DevEco Studio 内置的 JSON5 Schema 链接(报错里一般会给出 URL),对照看一眼当前 API 版本允许哪些字段,把不在里面的删掉即可。
经验 3:ArkTS 严格模式是"善意的麻烦",不要关闭它
strictMode 能不关闭就不要关闭。虽然它确实会让你多出几小时的编译错误要处理,但它抓到的每一个问题都是真问题------string | undefined 被当成 string 用、函数参数传少了、嵌套访问中间可能 undefined------这些在 JS 里可能只是 console.warn 的东西,在 ArkTS 严格模式下变成硬 ERROR,逼着你在编译期就把逻辑补全。我的做法是:先把严格模式下的 ERROR 全部清完,再去加业务代码。这样写出来的东西上设备跑起来稳定很多。
AtomGit 仓库链接 & 赛道二 PR
本文涉及的 HarmonyPCDemo 工程源码(含三轮修复的全部代码改动)已托管到 AtomGit(统一使用 AtomGit,不使用 GitCode):
👉 https://atomgit.com/wdracky/HarmonyPCDemo
仓库里同时包含完整的 .hvigor/outputs/build-logs/ 历史构建日志和 .hvigor/report/ 下的性能报告 JSON,你可以对照自己的环境逐行比对。
🔓 赛道二积分赛配套 PR(path A:三方库适配)
作为开源鸿蒙 PC 积分赛赛道二的参赛者,我同时完成了 path A ------将三方库适配到 OpenHarmonyPCDeveloper/build_in_harmonyos 主线框架。适配的库是 soundio 2.0.0(libsoundio,跨平台音频 I/O C 库,CMake 构建,纯 C、无额外依赖),目标是让它在 OHOS 上通过 CMake 原生构建,产出可被下游直接消费的二进制包。
PR #19174 的 Conan 配方(archives/s/soundio/2.0.0/conanfile.py )做了三个关键设计: 一是禁用所有平台特定音频后端 -------DENABLE_JACK=OFF -DENABLE_PULSEAUDIO=OFF -DENABLE_ALSA=OFF -DENABLE_COREAUDIO=OFF -DENABLE_WASAPI=OFF ,因为鸿蒙 PC 目前还没有对应的音频服务实现; 二是自发现 OHOS toolchain ------通过OHOS_NDK_HOME 环境变量 + 多路径 fallback 自动找到ohos.toolchain.cmake ,避免硬编码; 三是 ELF 签名 ------鸿蒙 PC 的 .so 需要签名才能在 XPM 上加载,配方在package() 阶段自动调用binary-sign-tool 完成。最终产物 10 个文件、+412 行,构建通过上游官方 ctest。
PR 详情:
| 项 | 值 |
|---|---|
| PR 编号 | #19174 |
| PR 链接 | https://atomgit.com/OpenHarmonyPCDeveloper/build_in_harmonyos/pull/19174 |
| 标题 | feat(soundio): 2.0.0 编译完成 |
| 源分支 | wdracky/feat/soundio-2.0.0 |
| 目标分支 | OpenHarmonyPCDeveloper/main |
| 变更规模 | +412 / -0,共 10 个文件 |
| commit | 19e7b8f1f104432a5ebcbda89aba99c90692644d |
配方结构:10 个文件各司其职
PR 新增了 archives/s/soundio/ 目录,共 10 个文件,按职责可以分成四组:
| 分组 | 文件 | 作用 |
|---|---|---|
| 构建配方 | conanfile.py |
定义 settings/options、取源、CMake 构建、安装与 ELF 签名 |
| 源码描述 | conandata.yml |
源码 URL + SHA256 校验,patches: [](无补丁) |
| 消费侧验证 | test_package/conanfile.py、test_package/test.c |
消费者测试,验证链接与初始化 |
| 元数据 | manifest.yaml × 2(软件级 + 版本级)、_meta.yaml、notes.md、README.md × 2、test_package/MANIFEST.yml |
记录构建系统、configure_options、适配要点与测试用例清单 |
conanfile.py:从取源到签名的完整链路
配方以 soundio 为包名、package_type="library",核心逻辑分四段:
- 配置阶段 :
configure()在共享库模式下移除fPIC,config_options()在 Windows 下移除fPIC;apply_conandata_patches走标准补丁流程,本库因 CMake 原生兼容 OHOS,patches留空。 - 工具链自发现 :新增
_ohos_toolchain(),依次从tools.cmake.cmaketoolchain:user_toolchain、环境变量OHOS_NDK_HOME、SDK 默认 glob 路径三处查找ohos.toolchain.cmake,找到即注入 CMake,避免把本机绝对路径硬编码进配方。 - 构建参数 :
build()以-DBUILD_STATIC_LIBS=ON、-DBUILD_DYNAMIC_LIBS=ON、-DBUILD_TESTS=ON、-DBUILD_EXAMPLE_PROGRAMS=OFF配置,同时关闭 JACK、PulseAudio、ALSA、CoreAudio、WASAPI 全部平台音频后端,并补充-DOHOS_ARCH=arm64-v8a,随后执行上游test目标。 - 安装与 ELF 签名 :
package()通过cmake --install安装到package_folder,再由_sign_binaries()对lib/**/*.so与*.so.*先用llvm-objcopy --remove-section .codesign清理旧签名段,再调用binary-sign-tool sign -inFile ... -selfSign 1完成签名------这一步在 OHOS 上不能省,否则产物无法被系统加载。
package_info() 使用 collect_libs 并回退到 ["soundio"],同时设置 cmake_file_name、cmake_target_name(soundio::soundio)与 pkg_config_name,让下游无论用 CMake 还是 pkg-config 都能正确找到库。
为什么禁用全部音频后端
OHOS 目前没有 JACK / PulseAudio / ALSA / CoreAudio / WASAPI 的对应实现,强行开启只会在链接期报一堆未定义符号。因此配方只保留 Threads(bionic pthreads 原生支持),让库以「纯计算 + 线程」的形态编译通过。这也意味着 soundio 在 OHOS 上暂时只能走 dummy 后端,实际出声需要后续接入 OHOS 音频框架------这一点在评审中被明确指出,见下文。
代码审查:一次很有价值的「打回」
PR 提交后,atomgit-bot 的自动审查给出了 request changes,结论是「不可合并」。这次打回反而让我把测试链路彻底补了一遍,问题清单如下:
| 优先级 | 数量 | 要点 |
|---|---|---|
| P0 | 1 | CHECK 宏传 3 个实参,而宏只接受 2 个 → test_package 无法编译 |
| P1 | 2 | _meta.yaml 不是合法 YAML(混入 README 正文 + PowerShell Set-Content 残留 + 未闭合 here-string,且泄露本机绝对路径);后端枚举断言数值偏移 1 |
| P2 | 2 | ver 为 NULL 时 strstr 空指针解引用;测试未覆盖任何后端,空壳库也能全绿(命中 R40 深度适配验证) |
| P3 | 3 | 未使用的 int err;CHECK(1, ...) 恒真断言;codeload URL 无镜像回退 |
最关键的 P0 是这样的:test.c 里宏定义为 #define CHECK(cond, desc),只接受两个形参且非可变参数,但调用处写成了
c
CHECK(strstr(ver, "2.0.0") != NULL,
"version string contains 2.0.0: got %s", ver);
预处理器会直接报 macro "CHECK" passed 3 arguments, but takes just 2,属于硬编译错误。这说明该 PR 的 test_package 从未真正编译执行过,后面那些断言(包括枚举断言偏移)自然也没被验证。修复方向有两个:去掉第三个实参、让描述为纯文本;或把宏改成可变参数 #define CHECK(cond, ...),用 snprintf 先把消息格式化进局部缓冲区再交给 fprintf("%s"),避免把用户字符串当格式串。
_meta.yaml 的问题则是典型的「编辑器误粘贴」:文件里混进了 README 的 Markdown 正文和 PowerShell 会话残留,真正的元数据键被埋在其中,还带出了本机绝对路径。这类问题在提交前用一次 yamllint 或 IDE 的 YAML 校验就能拦住。
这次打回教给我的三件事
- 测试必须真的跑过 。
conan create的test_package阶段是配方的最后一道闸门,如果它从未编译成功,整个「编译完成」的结论就是空的。 - 元数据文件也要过校验 。
_meta.yaml、manifest.yaml不是随手写的注释,它们会被 CI 解析,格式错误等于构建失败。 - 适配完整性要能被证明 。所有后端关闭后,至少要断言 dummy 后端可用(
soundio_connect/soundio_disconnect走通),否则「能编译」和「能用」之间还差一大截。
目前该 PR 处于「合并受阻:代码审查未通过(最低审查通过人数 1 人)」状态,我正在按上述清单逐项修复后重新提交。完整的配方文件与评审记录都可以在 PR 页面里逐条对照。
。
征文表格的"大赛的PR链接/代码仓"列,请填入此 PR 链接:
https://atomgit.com/OpenHarmonyPCDeveloper/build_in_harmonyos/pull/19174
作者声明
- AtomGit 账号:wdracky
- 参与项目:开源鸿蒙 PC 专项积分赛 --- 赛道二(path A + 本系列征文 path B)
- 最后更新:2026-10-28
本文所有报错原文、文件路径、代码片段均来自本人在 Windows 11 环境下使用 DevEco Studio 6.0 + hvigor 6.0.0 + API 19 的真实构建过程。如你在搭建过程中遇到和我不同的报错,欢迎在鸿蒙 PC 社区(https://harmonypc.csdn.net/)评论区留言交流。