动图魔方技术拆解 19:HarmonyOS SDK 配置修正与 Hvigor 构建排查

SEO 信息

  • SEO 标题:动图魔方技术拆解 19:HarmonyOS SDK 配置修正与 Hvigor 构建排查
  • SEO 摘要 :基于 HarmonyOS NEXT / ArkTS 项目"动图魔方",本文拆解一次真实的构建配置收口:为什么 build-profile.json5 里的 targetSdkVersioncompatibleSdkVersion 不能把 API 编号和 SDK 版本串混写,怎样用 Hvigor 命令复现构建结果,如何把签名材料、strictMode、模块列表和 3D 能力边界拆成可验收的排查清单。
  • 关键词:HarmonyOS, harmonyOS, ArkTS, Hvigor, build-profile.json5, SDK 配置, targetSdkVersion, compatibleSdkVersion, 构建排查
  • 文章封面doc/csdn-series/covers/cover-19-hvigor-sdk-build-check.jpg
  • 投稿方向:普通技术拆解文
  • 项目环境 :HarmonyOS SDK 6.1.0(23)、ArkTS、DevEco Studio、GIFRubiksCube
  • 验证时间:2026-06-27 16:30 +08:00
  • 验证对象build-profile.json5entry/src/main/ets/products/main/Index.ets、Hvigor assembleHap 输出、doc/screenshots_current/*.jpeg

第 18 篇把 3D 能力边界讲清楚之后,工程上马上会遇到另一个问题:能力路线写得再稳,如果本地构建配置不稳定,3D 入口、GIF 导出、主题和作品页验收都无法进入发布链路。第 19 篇只处理一件事:把 HarmonyOS SDK 版本串、Hvigor 构建命令、签名材料和警告分类拆成一套能复现、能排查、能交付的工程规则。

一、真实工程问题背景

这次不是"写一篇构建教程",而是项目里真的出现过一组容易互相影响的问题。为什么要单独写第 19 篇?因为动图魔方已经从普通 GIF 工具扩展到了素材导入、真实图片序列、3D 预览、服务卡片、深浅色主题和 CSDN 系列发布。功能越来越多以后,构建配置就不再是 DevEco Studio 自动生成的背景文件,而是发布链路的一部分。

  1. SDK 版本串容易写错 。项目讨论 3DGS 和 API 26 时,很容易把能力目标、设备 API 和当前构建 SDK 混成一句"切到 API 26"。但 build-profile.json5 实际需要的是当前工程可识别的 SDK 版本格式,例如 6.1.0(23)
  2. 构建命令必须可复制。如果只说"IDE 能跑",下一台机器、下一次自动化、下一篇 CSDN 文章都无法复验。本文使用的命令是 Hvigor CLI,不依赖编辑器当前页面。
  3. 签名材料不能被文章泄漏build-profile.json5 里真实存在 p12、p7b、证书路径和加密后的密码字段,文章只能展示结构和脱敏值,不能把完整材料当作代码块贴出去。
  4. 警告和错误要分级 。构建输出里有些任务是 UP-TO-DATE,有些是 Finished,真正要盯的是 BUILD SUCCESSFUL 或失败码。不能把所有黄色输出都当成阻塞,也不能把签名异常当成普通提示跳过。
  5. 功能验收依赖构建边界 。第 18 篇的 CapabilityService 已经把设备能力和构建能力分开;如果当前构建仍是 6.1.0(23),文章和产品说明就不能宣称真实 3DGS 执行体已经落地。

这类问题的风险很现实:用户看到的是一个能导出 GIF 的工具,测试看到的是一个需要稳定构建和安装的 HAP,文章读者看到的是一条技术路线。如果三者的版本口径不一致,后续每一篇文章都会被"到底按哪个 SDK 验收"拖住。

二、目标与边界

本文的目标不是升级 SDK,也不是演示所有 Hvigor 参数,而是把当前项目已经可用的构建口径固定下来。

目标 本文处理方式 为什么这么定
SDK 版本串 build-profile.json5 当前值为准 避免把 API 26 能力规划写成当前构建事实
Hvigor 命令 使用 assembleHap --mode module -p product=default --no-daemon 自动化和人工终端都能复现
签名配置 只展示脱敏结构 保护证书路径、密码和 profile 材料
构建结果 记录真实输出摘要 支撑文章不是空泛经验
3D 能力 继续承认当前包的边界 和第 18 篇能力路由保持一致
发布清单 写入 CSDN 系列本地记录 让第 20 篇收官能继承这次证据

边界也要说清楚:本文不替换证书、不重建 AGC profile、不改变包名,不修改 EntryAbility.ets 或页面业务逻辑。当前仓库还有用户已有的大量工程改动,本文只围绕构建配置、命令复现和发布文档展开。

三、源码对象与证据链

这篇文章的主对象是 build-profile.json5,但构建排查不能只盯一个文件。一个 HarmonyOS 工具 App 能否发布,至少要把工程级配置、入口页面、功能截图、构建命令和发布记录串起来。

证据类型 文件或命令 本文使用方式
工程级构建配置 build-profile.json5 说明 SDK、签名、模块和 strictMode
主页面入口 entry/src/main/ets/products/main/Index.ets 验证当前构建对象不是空壳页面
3D 能力层 entry/src/main/ets/features/threeD/services/CapabilityService.ets 承接第 18 篇能力边界
GIF 导出层 entry/src/main/ets/features/gif/services/ExportService.ets 确认核心业务仍进入构建
发布规划 doc/csdn-series/20篇系列规划.md 保持第 19 篇编号、标题和封面一致
发布记录 doc/csdn-series/publish-record.json 发布成功后记录 articleId、封面和状态
首页截图 https://i-blog.csdnimg.cn/direct/efeec2074b0247fe8b4629b27a1a90aa.jpeg 验收构建对象对应真实 App
编辑页截图 https://i-blog.csdnimg.cn/direct/11214b59c5d0419cb03f0357f69ac06e.jpeg 验收 GIF 工具主链路
3D 截图 https://i-blog.csdnimg.cn/direct/3d18169d59e94382b04727cfd1aa0d50.jpeg 验收第 18 篇延续能力
作品页截图 https://i-blog.csdnimg.cn/direct/8d56691f324d40d5885465386d1e5322.jpeg 验收发布前回看闭环

这里有一个取舍:文章要写真实工程问题,但不能把本地签名密钥、密码、证书材料完整暴露出来。所以后面的代码块会保留字段名和结构,只用 *** 表示敏感值。

四、先定位 SDK 配置,不要先猜报错

构建排查第一步不是去改页面,也不是重新安装 DevEco Studio,而是定位真正的配置文件。当前项目的 SDK 配置在工程级 build-profile.json5 里:

复制代码
rg -n "targetSdkVersion|compatibleSdkVersion|runtimeOS|strictMode" build-profile.json5

本次定位结果来自真实项目:

复制代码
build-profile.json5:22:        // 切到 API 26(版本串 26.0.0)以启用真实 3DGS 端侧能力。
build-profile.json5:23:        "targetSdkVersion": "6.1.0(23)",
build-profile.json5:24:        "compatibleSdkVersion": "6.1.0(23)",
build-profile.json5:25:        "runtimeOS": "HarmonyOS",
build-profile.json5:27:          "strictMode": {

这几行很有价值,因为它们暴露了一个常见问题:注释里仍然保留了"API 26 / 26.0.0"的历史说法,但实际可构建配置已经回到了 6.1.0(23)。如果文章或发布说明只引用注释,就会误导读者;如果只看实际字段,又会忘记为什么第 18 篇强调 3DGS 仍是预留路线。

我的处理规则是:构建以字段为准,路线以能力层为准,注释只作为历史线索。

五、SDK 版本串为什么不能和能力目标混写

HarmonyOS 工程里经常会同时出现三种说法:

  1. 当前 SDK 版本,例如 6.1.0(23)
  2. 设备或系统能力的 API 编号,例如讨论中的 API 26。
  3. 某个未来能力的产品目标,例如 3DGS 重建、Spatial Recon 或多模态素材生成。

这三者互相关联,但不是同一个配置项。官方文档里,build-profile.json5 是工程构建配置的一部分,Hvigor 也会读取工程级和模块级配置来组织 product、module、target、buildMode 和 buildOption。参考:命令行构建工具 hvigorwbuild-profile.json5 配置说明

项目里的脱敏配置可以写成这样:

复制代码
{
  "app": {
    "products": [
      {
        "name": "default",
        "signingConfig": "default",
        "targetSdkVersion": "6.1.0(23)",
        "compatibleSdkVersion": "6.1.0(23)",
        "runtimeOS": "HarmonyOS",
        "buildOption": {
          "strictMode": {
            "caseSensitiveCheck": true,
            "useNormalizedOHMUrl": true
          }
        }
      }
    ]
  }
}

这段配置表达的是"当前包按 HarmonyOS 6.1.0(23) 构建",不是"未来 3DGS 能力不做了"。第 18 篇的能力路由正是为了解决这个矛盾:页面可以展示 3D 入口,服务层可以保留 3DGS 执行体接入口,但当前构建结果必须按 6.1.0(23) 验收。

六、签名材料要检查,但文章和日志里要脱敏

build-profile.json5 里还有签名配置。这个部分对发布很关键,但不适合原样写到文章里。

复制代码
{
  "signingConfigs": [
    {
      "name": "default",
      "type": "HarmonyOS",
      "material": {
        "storeFile": "D:/.../aichiboboji.p12",
        "storePassword": "***",
        "keyAlias": "aichiboboji",
        "keyPassword": "***",
        "profile": "D:/.../动图魔方调试签名Debug.p7b",
        "certpath": "D:/.../图形处理项目调试证书.cer"
      }
    }
  ]
}

签名排查时,我会把它拆成四类问题:

检查项 需要看什么 不能做什么
storeFile p12 路径是否存在 不把完整本机路径当成通用教程
storePassword 是否由 DevEco/AGC 正确生成 不在文章或聊天里公开
profile 是否匹配 bundle、设备和调试/发布类型 不用错 profile 去解释运行失败
certpath 证书是否和 profile 同源 不把证书问题伪装成 ArkTS 编译问题

这也是为什么本文把"签名提醒"放进构建排查,而不是发布前最后一分钟再看。签名问题一旦拖到发布前,会和 SDK、设备、模块配置混在一起,排查成本会成倍上升。

七、Hvigor 命令要固定成可复制口径

本次构建使用的是项目根目录下的真实命令:

复制代码
$env:DEVECO_SDK_HOME = 'D:\HuaweiDevelopFormalStudy\DevEco Studio\sdk'
$env:Path = 'D:\HuaweiDevelopFormalStudy\DevEco Studio\jbr\bin;D:\HuaweiDevelopFormalStudy\DevEco Studio\sdk\default\openharmony\toolchains;D:\HuaweiDevelopFormalStudy\DevEco Studio\tools\node;' + $env:Path
& 'D:\HuaweiDevelopFormalStudy\DevEco Studio\tools\hvigor\bin\hvigorw.bat' assembleHap --mode module -p product=default --no-daemon

这里有几个细节值得保留:

  1. DEVECO_SDK_HOME 明确指向本机 DevEco SDK。
  2. Path 里显式加入 JBR、toolchains 和 DevEco node。
  3. assembleHap 只构建 HAP,不把 AppGallery 发布动作混进来。
  4. --mode module -p product=default 对应当前工程的默认 product。
  5. --no-daemon 让自动化日志更容易收尾,不依赖残留 daemon 状态。

这条命令和官方命令行构建思路一致:把构建从 IDE 当前状态里抽离出来,形成可重复执行的终端口径。

八、真实构建输出怎么读

本次实测输出的关键结果是:

复制代码
> hvigor UP-TO-DATE :entry:default@CompileArkTS...
> hvigor UP-TO-DATE :entry:default@PackageHap...
> hvigor UP-TO-DATE :entry:default@SignHap...
> hvigor Finished :entry:assembleHap... after 1 ms
> hvigor BUILD SUCCESSFUL in 3 s 189 ms

这段日志说明三件事:

  1. ArkTS 编译阶段没有报错。
  2. HAP 打包和签名阶段没有阻塞。
  3. 本次构建很多任务是 UP-TO-DATE,表示缓存命中,不代表没有经过构建系统检查。

如果后续遇到失败,我会先按阶段归类:

阶段 常见问题 排查入口
CreateBuildProfile SDK 字段、product、module 配置错误 build-profile.json5
CompileArkTS 语法、类型、导入路径、API 签名不匹配 entry/src/main/ets/**
ProcessResource 资源路径、媒体命名、profile 配置错误 entry/src/main/resources/**
PackageHap 模块依赖、产物目录、oh-package 配置 entry/build-profile.json5oh-package.json5
SignHap p12、p7b、证书或 alias 不匹配 signingConfigs

这张表比"构建失败了怎么办"更有用,因为它把问题先拆到构建阶段,再去定位文件,而不是看见红字就去改业务代码。

九、截图证据与源码映射

构建通过只是底线。发布前还需要证明这个包对应的是当前功能集,而不是一个空壳构建。下面四张截图分别对应功能入口、编辑主链路、3D 能力和作品回看。

截图 对应源码位置 需要证明的规则
首页功能入口 entry/src/main/ets/products/main/Index.ets:28 当前构建入口是主产品页
编辑器主链路 entry/src/main/ets/products/main/Index.ets:591 GIF 导出仍走 ExportService.exportGif()
3D 预览入口 entry/src/main/ets/products/main/Index.ets:889 3D 入口仍由 Model3DView 承接
作品页回看 entry/src/main/ets/products/main/Index.ets:595 导出结果会进入本地作品列表
能力路由 entry/src/main/ets/features/threeD/services/CapabilityService.ets:17 构建能力和设备能力分开判断
导出服务 entry/src/main/ets/features/gif/services/ExportService.ets:20 构建覆盖核心 GIF 服务

这里的重点不是截图好不好看,而是截图能否和源码位置互相解释。构建排查文章如果只有命令输出,读者会不知道这个包到底覆盖了哪些业务;只有截图,又会像产品展示页。两者连起来,才是工程证据。

十、构建配置和 3D 能力边界的关系

第 18 篇里,CapabilityService 把能力路由拆成设备能力和构建能力。第 19 篇需要承接这个判断,因为 SDK 配置不只是"能不能编译",它还会决定文章怎么写、测试怎么验收。

复制代码
export interface CapabilityResult {
  route: '3dgs' | 'render' | 'synthetic';
  deviceSupportsRecon: boolean;
  buildSupportsRecon: boolean;
  message: string;
}

这类结构的价值在于它不让页面直接猜 SDK:

复制代码
const cap = CapabilityService.detect3D();
if (cap.route === '3dgs') {
  // 未来真实 3DGS 执行体接入后走这里。
} else if (cap.route === 'render') {
  // 当前构建优先走实时 3D 预览与合成导出。
} else {
  // 设备或构建都不满足时,保留单图浅 3D 降级。
}

如果 build-profile.json5 当前是 6.1.0(23),那么第 18 篇、第 19 篇和发布说明都应该保持同一个口径:当前版本已有 3D 预览和能力路由,真实 3DGS 执行体仍是预留路线。这个边界看起来保守,但它能保护后续发布。

十一、复现命令与日志留存

为了让下次自动化或人工复核能快速定位,我把本文用到的命令整理成一组最小集合。

复制代码
rg -n "targetSdkVersion|compatibleSdkVersion|runtimeOS|strictMode" build-profile.json5

rg -n "CapabilityService|Model3DView|ExportService|StorageService" entry/src/main/ets/products/main/Index.ets entry/src/main/ets/features -g "*.ets"

Get-ChildItem -Path 'doc\screenshots_current' -Filter '*.jpeg' | Select-Object -First 20 -ExpandProperty FullName

$env:DEVECO_SDK_HOME = 'D:\HuaweiDevelopFormalStudy\DevEco Studio\sdk'
$env:Path = 'D:\HuaweiDevelopFormalStudy\DevEco Studio\jbr\bin;D:\HuaweiDevelopFormalStudy\DevEco Studio\sdk\default\openharmony\toolchains;D:\HuaweiDevelopFormalStudy\DevEco Studio\tools\node;' + $env:Path
& 'D:\HuaweiDevelopFormalStudy\DevEco Studio\tools\hvigor\bin\hvigorw.bat' assembleHap --mode module -p product=default --no-daemon

node tools/check_csdn_article_quality.js 19

本次构建验收摘要:

复制代码
BUILD SUCCESSFUL in 3 s 189 ms

本次源码定位摘要:

复制代码
entry/src/main/ets/products/main/Index.ets:28:@Entry
entry/src/main/ets/products/main/Index.ets:591:const work = await ExportService.exportGif(this.ctx(), preset, signal);
entry/src/main/ets/products/main/Index.ets:889:Model3DView({ viewSize: this.isWide() ? 360 : 320 })
entry/src/main/ets/features/threeD/services/CapabilityService.ets:17:export class CapabilityService

这些命令的价值在于可复现。下次如果有人说"构建又不稳定了",我们可以先跑同一组命令,看问题发生在配置、源码、资源、签名还是平台环境。

十二、常见错误分类与修正顺序

构建排查最怕把所有问题混在一起。我的顺序是先配置,再环境,再源码,最后签名和平台。

顺序 检查点 通过标准 风险
1 项目根目录 当前路径是 GIFRubiksCube 在错误项目里构建
2 SDK 环境变量 DEVECO_SDK_HOME 指向 DevEco SDK 使用旧 SDK 或缺 toolchains
3 SDK 字段 targetSdkVersioncompatibleSdkVersion 是当前可识别版本 API 编号和 SDK 串混写
4 product product=default 存在 命令指向不存在的 product
5 模块列表 entry 模块在 modules 只改页面但模块没进构建
6 ArkTS 编译 CompileArkTS 通过 API 签名、导入路径、类型错误
7 资源处理 ProcessResource 通过 图片、profile、路由配置错误
8 签名 SignHap 通过 profile、证书或 alias 不匹配
9 HAP 产物 assembleHap 成功 缓存或产物目录异常
10 截图验收 当前功能截图可对应源码 构建成功但不是目标版本

这个顺序有一点朴素,但很有效:先确保工程能被构建系统理解,再讨论页面和业务。否则每次构建失败都会让人误以为是刚改的 ArkUI 代码坏了。

十三、本文不解决但必须记录的边界

第 19 篇也有几个不越界的地方:

  1. 不把调试签名当成上架签名。调试 profile 能让本地构建通过,不等于 AppGallery 发布材料已经齐全。
  2. 不用构建成功证明所有设备兼容。compatibleSdkVersion 和设备镜像仍然要在安装阶段复核。
  3. 不把 3DGS 预留说成当前已落地。当前构建只证明项目能在 6.1.0(23) 下通过,不能证明 API 26 执行体已经存在。
  4. 不把 UP-TO-DATE 误读成未构建。它说明 Hvigor 判断任务无需重跑,最终仍以 BUILD SUCCESSFUL 为准。
  5. 不在文章中公开签名密码和完整证书路径。工程排查可以记录"字段存在",不能泄漏材料。

这些边界让文章更可信。技术文不是把所有结果说满,而是把可以证明的事情证明清楚,把暂时不能证明的事情留在后续路线里。

十四、工程验收清单

验收项 结果 证据
SDK 字段已定位 通过 build-profile.json5:23-24
当前构建版本口径明确 通过 targetSdkVersion / compatibleSdkVersion 均为 6.1.0(23)
Hvigor 命令可复现 通过 assembleHap --mode module -p product=default --no-daemon
ArkTS 编译通过 通过 CompileArkTS 输出 UP-TO-DATE
HAP 打包通过 通过 PackageHap / SignHap 未阻塞
构建最终成功 通过 BUILD SUCCESSFUL in 3 s 189 ms
签名材料已脱敏说明 通过 本文只展示字段结构和 ***
3D 能力边界未夸大 通过 CapabilityService 仍按构建能力路由
截图和源码有映射 通过 首页、编辑、3D、作品页四张截图
第 19 篇具备发布前本地质检入口 通过 node tools/check_csdn_article_quality.js 19

十五、工程复盘

这次构建排查带来的最大收益,是把"版本口径"变成了一个可检查对象。以前写文章时很容易把未来能力、当前 SDK、构建命令和截图验收混在一起;现在它们各自有位置:

  1. build-profile.json5 负责当前构建事实。
  2. CapabilityService.ets 负责能力路由和降级口径。
  3. Hvigor 命令负责可复现构建。
  4. 截图负责证明构建对象对应真实功能。
  5. publish-record.json 负责记录发布状态和 CSDN 链接。

这也是为什么第 19 篇适合放在系列尾声。前 18 篇已经拆了页面、导出、素材、存储、主题、3D 和验收,第 19 篇把它们背后的工程构建底座补齐。这样第 20 篇做发布前清单时,就不需要重新解释"为什么构建也算技术内容"。

十六、下一篇衔接

第 20 篇是系列收官:动图魔方技术拆解 20:HarmonyOS 工具 App 发布前工程清单与复盘

它会把前面 19 篇分散的证据收成一个发布前清单:

  1. 功能链路是否覆盖素材导入、编辑、导出、作品回看和 3D 入口。
  2. 截图、构建输出、本地质检和 CSDN 发布记录是否能互相印证。
  3. 哪些能力属于当前版本,哪些能力属于后续 SDK 或平台能力演进。
  4. doc/csdn-series 如何作为项目文档资产继续维护,而不是发布后就被遗忘。

如果说第 19 篇解决的是"这个工程怎么稳定构建",第 20 篇要解决的就是"这个工程怎么带着清晰证据完成一轮发布复盘"。