在这里插入图片描述

HarmonyKit | 鸿蒙开发:build-profile.json5 SDK 版本与签名配置详解

引言:两万个字符的配置,五个关键决策

HarmonyKit 的配置文件加在一起不到 500 行,但背后的决策逻辑远比代码量复杂。build-profile.json5 是鸿蒙项目的"总控制台"——一个配置项的变更就可能影响 HAP 体积、API 可用范围、签名方式、编译警告和上架审核结果。

这篇文章以 HarmonyKit 的实际配置为例,从项目级到模块级逐层拆解 build-profile.json5 的每一个配置节点,解释在什么场景下应该选择什么配置值,以及错误的配置会带来什么后果。

项目仓库:https://atomgit.com/VON-/harmony-kit

配置的三个层级

在深入了解每个字段之前,先建立全局视角。鸿蒙项目的构建配置分为三个层级:

层级 文件位置 作用域
项目级 ./build-profile.json5 所有模块共享的签名、产品、构建模式配置
模块级 ./entry/build-profile.json5 单个模块的构建选项、混淆规则、target 配置
引擎级 ./hvigor/hvigor-config.json5 hvigor 构建引擎本身的行为配置

三个层级不是平等的——项目级配置"规定可以做什么",模块级配置"选择怎么做",引擎级配置"以什么方式做"。

项目级 build-profile.json5 全解析

HarmonyKit 的项目级配置完整如下:
在这里插入图片描述

{
  "app": {
    "signingConfigs": [
      {
        "name": "default",
        "type": "HarmonyOS",
        "material": {
          "certpath": "/Users/wangxinjie/.ohos/config/default_harmonykit_xxx.cer",
          "keyAlias": "debugKey",
          "keyPassword": "0000001A9C...",
          "profile": "/Users/wangxinjie/.ohos/config/default_harmonykit_xxx.p7b",
          "signAlg": "SHA256withECDSA",
          "storeFile": "/Users/wangxinjie/.ohos/config/default_harmonykit_xxx.p12",
          "storePassword": "0000001AA1..."
        }
      }
    ],
    "products": [
      {
        "name": "default",
        "signingConfig": "default",
        "targetSdkVersion": "6.0.2(22)",
        "compatibleSdkVersion": "6.0.2(22)",
        "runtimeOS": "HarmonyOS",
        "buildOption": {
          "strictMode": {
            "caseSensitiveCheck": true,
            "useNormalizedOHMUrl": true
          }
        }
      }
    ],
    "buildModeSet": [
      { "name": "debug" },
      { "name": "release" }
    ]
  },
  "modules": [
    {
      "name": "entry",
      "srcPath": "./entry",
      "targets": [
        {
          "name": "default",
          "applyToProducts": ["default"]
        }
      ]
    }
  ]
}

signingConfigs:签名配置数组

这个数组可以包含多个签名配置——典型场景是开发调试签名和生产发布签名分离:
在这里插入图片描述

"signingConfigs": [
  {
    "name": "debug",        // 开发调试专用签名
    "type": "HarmonyOS",
    "material": { /* 自动生成的调试证书 */ }
  },
  {
    "name": "release",      // 生产发布专用签名
    "type": "HarmonyOS",
    "material": { /* AppGallery 签发的正式证书 */ }
  }
]

HarmonyKit 目前只有一个 default 签名配置,因为它还没有上架 AppGallery,只使用 DevEco Studio 自动生成的调试证书。

signingConfigs 的关键配置项解读

  • name:签名的逻辑名称,被 products[].signingConfig 引用。
  • type:固定为 "HarmonyOS"
  • material.certpath.cer 证书文件的绝对路径。这是公钥证书,用于验证签名。
  • material.storeFile.p12 密钥库文件路径。包含私钥和证书链,是签名操作的核心。
  • material.keyAlias:密钥库中密钥的别名。默认 "debugKey"
  • material.profile.p7b Provisioning Profile 文件路径。描述应用在设备上的运行权限。
  • material.signAlg:签名算法。SHA256withECDSA 使用 ECDSA 椭圆曲线算法配合 SHA-256 哈希。
  • material.keyPassword / storePassword:密钥和密钥库的密码。调试证书的密码是固定的、自动生成的;生产证书的密码需要自己保管。

安全提醒keyPasswordstorePassword 是敏感信息。HarmonyKit 是开源项目,调试密码虽然由 IDE 自动生成且不具有生产意义上的安全风险,但我们仍需避免将这些值硬编码到公开的配置文件中。实际开发中,密码可以从环境变量或加密的 keystore 中读取。

products:产品定义

products 数组让你可以为同一个应用定义多个产品变体。每个产品可以有不同的签名配置、SDK 版本和构建选项。

HarmonyKit 只有一个 default 产品。多产品场景的例子:

"products": [
  {
    "name": "phone",           // 手机版
    "signingConfig": "release",
    "targetSdkVersion": "6.0.2(22)",
    "compatibleSdkVersion": "5.0.0(12)",
    "runtimeOS": "HarmonyOS",
    "buildOption": { /* ... */ }
  },
  {
    "name": "tablet",           // 平板版
    "signingConfig": "release",
    "targetSdkVersion": "6.0.2(22)",
    "compatibleSdkVersion": "5.0.0(12)",
    "runtimeOS": "HarmonyOS",
    "buildOption": { /* ... */ }
  }
]

targetSdkVersion vs compatibleSdkVersion:两个 SDK 版本的区别

这是整个 build-profile.json5 中最重要的配置,也是最容易被误解的。HarmonyKit 将两者都设为 "6.0.2(22)",但它们的含义完全不同:

targetSdkVersion:告诉系统"我为这个版本的 API 做了适配和测试"。如果系统运行在更高的 API 版本上,系统会启用兼容行为以确保应用正常工作。举例:如果 targetSdkVersion 是 API 18,但设备运行 API 22,系统可能会对某些 API 行为做向后兼容——比如权限弹窗的样式、通知渠道的行为等。

compatibleSdkVersion:告诉系统"我最低要求这个版本的 API,低于此版本的设备无法安装"。这是安装门槛。如果设置 compatibleSdkVersion: "6.0.2(22)",那么运行 API 21 或更低版本的设备将无法安装此应用。

两者的关系是:compatibleSdkVersion <= targetSdkVersion

那么什么时候应该将 compatibleSdkVersion 设得比 targetSdkVersion 低?

当你的应用使用了 API 22 的新特性,但对这些特性做了降级处理时。例如:

// API 22 引入了新的动画 API
if (deviceInfo.sdkApiVersion >= 22) {
  // 使用 API 22 的新动画
  animateTo({ duration: 300, curve: curves.springMotion() });
} else {
  // 降级为 API 21 的普通动画
  animateTo({ duration: 300, curve: Curve.EaseOut });
}

这种情况下,你可以设置 targetSdkVersion: "6.0.2(22)"compatibleSdkVersion: "5.0.3(21)",让更多设备可以安装你的应用,只是低版本设备上的体验会退化。

HarmonyKit 选择两者都为 "6.0.2(22)",原因很简单:项目使用了 @kit.UIDesignKit(HDS 组件),该 Kit 的最低要求就是 API 22。技术栈决定了兼容性下限。

buildOption.strictMode:严格模式

HarmonyKit 开启了两项严格检查:

"strictMode": {
  "caseSensitiveCheck": true,
  "useNormalizedOHMUrl": true
}

caseSensitiveCheck:大小写敏感检查。开发环境通常是 macOS(默认文件系统大小写不敏感),但 HarmonyOS 设备上的文件系统可能是大小写敏感的。开启此检查可以避免"开发环境正常,真机运行时找不到文件"的问题。

一个常见的大小写问题:

// 开发环境能通过(macOS)
import { CopyButton } from '../../components/copybutton';  // 小写 b
// 真机上可能找不到文件,因为实际文件名是 CopyButton.ets

开启 caseSensitiveCheck: true 后,编译器会严格校验 import 路径的大小写与实际文件名完全一致。这是一个"开局加一个配置,后续少十个 bug"的选项。

useNormalizedOHMUrl:强制使用标准化的 OHM URL 格式。OHM URL 是鸿蒙生态的统一模块引用格式,格式为 @scope/package/path。开启此选项后:

// 允许:标准 OHM URL
import { router } from '@kit.ArkUI';

// 也允许:相对路径
import { ToolCard } from '../components/ToolCard';

// 警告:非标准路径格式
import { ToolCard } from '../components\\ToolCard';  // 反斜杠

这个选项主要防范 Windows 开发环境中的路径分隔符问题(反斜杠 vs 正斜杠)。

strictMode 还包括以下可选检查

  • useStateVarCheck:检查 @State 变量的使用是否符合规范
  • noExternalImportByPath:禁止通过绝对路径引用模块外部文件
  • noEtsCodeInJsFile:禁止在 .js 文件中使用 .ets 语法

buildModeSet:构建模式

HarmonyKit 定义了两个构建模式:

"buildModeSet": [
  { "name": "debug" },
  { "name": "release" }
]

这两个模式对应的行为差异(由 hvigor 内置插件处理):

行为 debug release
代码压缩 关闭 开启(可配置)
代码混淆 关闭 取决于 obfuscation 配置
SourceMap 生成 不生成
HAP 签名 调试签名 生产签名
日志输出 保留 可被优化掉

在 HarmonyKit 开发中,debug 模式用于本地开发和调试,release 模式用于打包测试和上架准备。

modules:模块配置

"modules": [
  {
    "name": "entry",
    "srcPath": "./entry",
    "targets": [
      {
        "name": "default",
        "applyToProducts": ["default"]
      }
    ]
  }
]

modules 数组列出了项目中的所有模块(entry、feature、HSP、HAR 等)。HarmonyKit 只有一个 entry 模块。

  • name:模块的逻辑名称,与 module.json5 中的 module.name 对应。
  • srcPath:模块目录相对于项目根目录的路径。
  • targets:模块的构建目标。每个 target 可以声明它适用于哪些 product(通过 applyToProducts)。

applyToProducts: ["default"] 表示该 target 在构建 default 产品时生效。如果定义了多个 product(如 phone 和 tablet),可以指定不同的 target 应用到不同的 product。

多模块项目的典型 modules 配置

"modules": [
  {
    "name": "entry",
    "srcPath": "./entry",
    "targets": [
      { "name": "phone", "applyToProducts": ["phone"] },
      { "name": "tablet", "applyToProducts": ["tablet"] }
    ]
  },
  {
    "name": "shared_ui",
    "srcPath": "./shared_ui",  // HSP 共享包
    "targets": [
      { "name": "default", "applyToProducts": ["phone", "tablet"] }
    ]
  }
]

模块级 build-profile.json5 解析

HarmonyKit 的模块级配置:

{
  "apiType": "stageMode",
  "buildOption": {
    "resOptions": {
      "copyCodeResource": {
        "enable": false
      }
    }
  },
  "buildOptionSet": [
    {
      "name": "release",
      "arkOptions": {
        "obfuscation": {
          "ruleOptions": {
            "enable": false,
            "files": ["./obfuscation-rules.txt"]
          }
        }
      }
    }
  ],
  "targets": [
    { "name": "default" },
    { "name": "ohosTest" }
  ]
}

apiType:API 模型类型

固定为 "stageMode"。Stage 模型是 HarmonyOS 3.1+ 推荐的应用模型。与旧的 FA(Feature Ability)模型相比,Stage 模型提供了更好的生命周期管理、跨设备迁移和原子化服务支持。

HarmonyOS 正在逐步淘汰 FA 模型。新项目应该统一使用 Stage 模型。

buildOption.resOptions.copyCodeResource

"resOptions": {
  "copyCodeResource": {
    "enable": false
  }
}

这个选项控制是否将 rawfile 目录中的代码文件(.ets.ts.js)视为"代码资源"并复制到资源包中。关闭它可以:

  1. 减小 HAP 体积(不包含不必要的代码文件)
  2. 避免意外将源码暴露在可提取的应用包中
  3. 加快资源处理阶段的构建速度

HarmonyKit 不需要从 rawfile 动态加载代码(如动态执行 .abc 文件),所以关闭此选项。

buildOptionSet:按构建模式的选项覆盖

buildOptionSet 允许你为不同的构建模式(debug/release)设置不同的构建选项。HarmonyKit 只为 release 模式配置了选项:

"buildOptionSet": [
  {
    "name": "release",
    "arkOptions": {
      "obfuscation": {
        "ruleOptions": {
          "enable": false,
          "files": ["./obfuscation-rules.txt"]
        }
      }
    }
  }
]

代码混淆(obfuscation):HarmonyKit 在 release 模式下也关闭了混淆(enable: false)。这个决策有四个理由:

  1. 开源透明度:HarmonyKit 是开源项目(MIT License)。混淆后的代码会让社区贡献者无法阅读理解源码,违反开源精神。
  2. HAP 体积不大:HarmonyKit 的 HAP 约 3MB,远低于 100MB 上限。混淆带来的体积优化(通常 10%-20%)收益不高。
  3. 调试成本:release 模式下如果出现问题(如 AppGallery 审核失败),未混淆的代码便于通过错误堆栈定位问题。
  4. 贡献者友好:混淆后的代码对 APK 逆向难度提升有限(HarmonyKit 没有核心算法需要保护),却大大增加了贡献者阅读源码的成本。

如果你需要开启混淆,需要提供混淆规则文件(obfuscation-rules.txt),规则语法类似于 ProGuard。典型规则:

# 保留所有 export 的类名和方法名(否则外部模块无法引用)
-keep public class * {
    public *;
}

# 保留 UIAbility 子类(系统通过类名查找)
-keep class * extends UIAbility

# 丢弃所有日志输出
-assumenosideeffects class hilog {
    public *** debug(...);
    public *** info(...);
}

targets:模块构建目标

"targets": [
  { "name": "default" },
  { "name": "ohosTest" }
]

default target 用于常规构建,ohosTest target 用于自动化测试构建。在 DevEco Studio 中,"Run"按钮使用 default target,"Run Test"按钮使用 ohosTest target。

HarmonyKit 的测试目录结构:

entry/src/
├── main/       # 对应 default target
├── ohosTest/   # 对应 ohosTest target(UI 自动化测试)
└── test/       # 本地单元测试

配置变更的影响范围分析

理解"改了某个配置会影响什么"比记住每个配置项更重要。以下是 HarmonyKit 开发中实际遇到的配置变更影响链:

场景:修改 compatibleSdkVersion

compatibleSdkVersion: "6.0.2(22)" → "5.0.0(12)"

影响链:

  1. 可以安装在更多设备上(API 12+ 的设备都可以安装)
  2. @kit.UIDesignKit 中的某些 HDS 组件在 API 12 上不可用
  3. 编译器不会报错(因为编译 target 还是 API 22),但真机运行时会崩溃
  4. 需要在代码中添加运行时 API 版本检查

场景:修改 targetSdkVersion

targetSdkVersion: "6.0.2(22)" → "5.0.1(18)"

影响链:

  1. 编译时只能使用 API 18 及以下版本的 API
  2. 代码中使用的 API 22 新特性会报编译错误
  3. 需要移除对新 API 的引用或降级实现
  4. @kit.UIDesignKit 中的 API 22 专属方法变得不可用

场景:将 release 的 obfuscation 改为 true

"enable": false → true

影响链:

  1. release HAP 中类名、方法名被混淆为短名称(a、b、c…)
  2. HAP 体积减少约 10%-20%
  3. 错误堆栈不再可读(需要 mapping 文件还原)
  4. 社区贡献者不能直接通过阅读 release 产物理解代码
  5. 需要保留 mapping 文件用于审核问题的堆栈还原

配置文件的最佳实践

基于 HarmonyKit 的开发经验,总结以下最佳实践:

1. signingConfigs 至少包含 debug 和 release 两个配置

不要图方便把 debug 证书用在 release 构建中。debug 证书由 IDE 自动生成,有效期有限且不被 AppGallery 信任。release 构建必须使用 AppGallery 签发的正式证书。

2. compatibleSdkVersion 不要随意调低

compatibleSdkVersion 越低,兼容的设备越多(是好事),但你需要为所有低版本设备处理 API 差异(是成本)。一个合理的策略是:将 compatibleSdkVersion 设置为项目所用 Kit 套件的最低支持版本。HarmonyKit 因为使用了 @kit.UIDesignKit,所以最低版本就是 API 22。

3. strictMode 全部开启

caseSensitiveCheckuseNormalizedOHMUrl 都是在编译阶段进行检查,不影响运行时性能和 HAP 体积。开启它们等于免费获得了一层"最佳实践校验"。

4. buildModeSet 至少包含 debug 和 release

这是一个几乎所有项目都会保持的默认配置。只有在需要额外的构建模式时(如 staging、beta)才扩展数组。

5. 代码文件不要进 rawfile

copyCodeResource: false 应该是默认选择。只有当你确实需要从 rawfile 动态加载代码时才开启——比如实现热更新或插件化架构。

配置即文档

最后谈一个认知层面的观点:build-profile.json5 不仅是配置文件,也是一种文档。一个新人打开项目,他看到的第一个"有信息量"的东西(除了 README)就是 build-profile.json5。通过它,你能推断出:这个应用用什么 SDK 版本?是否有多个产品变体?是否做代码混淆?支持哪些设备?

因此,配置文件的注释很重要。HarmonyKit 的配置虽然简洁,但每个关键字段都有明确的场景对应——这不是为了配置而配置,而是为了让所有协作者能在五分钟内理解项目的构建策略。

项目仓库:https://atomgit.com/VON-/harmony-kit

Logo

作为“人工智能6S店”的官方数字引擎,为AI开发者与企业提供一个覆盖软硬件全栈、一站式门户。

更多推荐