鸿蒙PC构建实战:hvigor modelVersion 降级 + schema 清理 + ArkTS 编译三连坑完整复盘

发布时间:2026/10/29 19:58:40
鸿蒙PC构建实战:hvigor modelVersion 降级 + schema 清理 + ArkTS 编译三连坑完整复盘

欢迎加入开源鸿蒙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 支持
    • 第二轮:schema 校验 buildVersion 非法
    • 第三轮:ArkTS 的 compilation ERROR
  • 构建成功日志
  • 三条通用经验总结
    • 经验 1:先把所有 modelVersion 统一到最低兼容版本
    • 经验 2:API 升级时重点检查 JSON5 schema 的字段去留
    • 经验 3:ArkTS 严格模式是"善意的麻烦",不要关闭它
  • AtomGit 仓库链接 & 赛道二 PR
    • 🔓 赛道二积分赛配套 PR(path A:三方库适配)
    • 配方结构:10 个文件各司其职
    • conanfile.py:从取源到签名的完整链路
    • 为什么禁用全部音频后端
    • 代码审查:一次很有价值的「打回」
    • 这次打回教给我的三件事
  • 作者声明

适用读者 / 前置知识 / 涉及工具版本

适用读者:第一次接触鸿蒙 PC 开发的同学、从 HarmonyOS 手机端迁移到 PC 端的开发者、尝试用 DevEco Studio 6.0 搭建 API 19 工程但构建不过的新手。

前置知识:了解 JSON5 配置文件的基本语法、知道 hvigor 是鸿蒙的构建工具(类似 Android 的 Gradle / Web 的 Vite)、能在 DevEco Studio 里打开项目并找到 Build 按钮即可。不需要任何鸿蒙开发经验。

涉及工具和版本(这个版本号非常重要,鸿蒙工具链更新极快,版本对不上报错可能完全不一样):

组件版本
DevEco Studio6.0(Build 6.0.1.100)
hvigor6.0.0
OpenHarmony SDK / API5.1.1 (API 19)
操作系统Windows 11
Node.jsv18+

踩坑故事(按时间顺序)

下面这张流程图把整条踩坑链路串了起来,红色节点是三次构建失败的位置。你可以按图索骥:先看自己卡在哪一个红色节点,再直接跳到对应小节看报错原文和修复方案,不必从头读。

创建工程(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 个文件需要修改:

#文件路径改动
1hvigor/hvigor-config.json5"modelVersion": "6.1.1"→"modelVersion": "6.0.0"
2oh-package.json5"modelVersion": "6.1.1"→"modelVersion": "6.0.0"
3demo/hvigor/hvigor-config.json5同上
4demo/oh-package.json5同上

修改后的hvigor/hvigor-config.json5关键部分长这样:

{"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,所以是两个文件:

#文件路径操作
1AppScope/app.json5删除"buildVersion": "x.y.z"那一行
2demo/AppScope/app.json5同上

修复前的AppScope/app.json5(示意):

{"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(当前仓库版本):

{"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 个文件
commit19e7b8f1f104432a5ebcbda89aba99c90692644d

配方结构: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,结论是「不可合并」。这次打回反而让我把测试链路彻底补了一遍,问题清单如下:

优先级数量要点
P01CHECK宏传 3 个实参,而宏只接受 2 个 →test_package无法编译
P12_meta.yaml不是合法 YAML(混入 README 正文 + PowerShellSet-Content残留 + 未闭合 here-string,且泄露本机绝对路径);后端枚举断言数值偏移 1
P22ver为 NULL 时strstr空指针解引用;测试未覆盖任何后端,空壳库也能全绿(命中 R40 深度适配验证)
P33未使用的int err;CHECK(1, ...)恒真断言;codeload URL 无镜像回退

最关键的 P0 是这样的:test.c里宏定义为#define CHECK(cond, desc),只接受两个形参且非可变参数,但调用处写成了

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 校验就能拦住。

这次打回教给我的三件事

  1. 测试必须真的跑过。conan create的test_package阶段是配方的最后一道闸门,如果它从未编译成功,整个「编译完成」的结论就是空的。
  2. 元数据文件也要过校验。_meta.yaml、manifest.yaml不是随手写的注释,它们会被 CI 解析,格式错误等于构建失败。
  3. 适配完整性要能被证明。所有后端关闭后,至少要断言 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/)评论区留言交流。