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

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:
.p7bProvisioning Profile 文件路径。描述应用在设备上的运行权限。 - material.signAlg:签名算法。
SHA256withECDSA使用 ECDSA 椭圆曲线算法配合 SHA-256 哈希。 - material.keyPassword / storePassword:密钥和密钥库的密码。调试证书的密码是固定的、自动生成的;生产证书的密码需要自己保管。
安全提醒:keyPassword 和 storePassword 是敏感信息。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)视为"代码资源"并复制到资源包中。关闭它可以:
- 减小 HAP 体积(不包含不必要的代码文件)
- 避免意外将源码暴露在可提取的应用包中
- 加快资源处理阶段的构建速度
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)。这个决策有四个理由:
- 开源透明度:HarmonyKit 是开源项目(MIT License)。混淆后的代码会让社区贡献者无法阅读理解源码,违反开源精神。
- HAP 体积不大:HarmonyKit 的 HAP 约 3MB,远低于 100MB 上限。混淆带来的体积优化(通常 10%-20%)收益不高。
- 调试成本:release 模式下如果出现问题(如 AppGallery 审核失败),未混淆的代码便于通过错误堆栈定位问题。
- 贡献者友好:混淆后的代码对 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)"
影响链:
- 可以安装在更多设备上(API 12+ 的设备都可以安装)
- 但
@kit.UIDesignKit中的某些 HDS 组件在 API 12 上不可用 - 编译器不会报错(因为编译 target 还是 API 22),但真机运行时会崩溃
- 需要在代码中添加运行时 API 版本检查
场景:修改 targetSdkVersion
targetSdkVersion: "6.0.2(22)" → "5.0.1(18)"
影响链:
- 编译时只能使用 API 18 及以下版本的 API
- 代码中使用的 API 22 新特性会报编译错误
- 需要移除对新 API 的引用或降级实现
@kit.UIDesignKit中的 API 22 专属方法变得不可用
场景:将 release 的 obfuscation 改为 true
"enable": false → true
影响链:
- release HAP 中类名、方法名被混淆为短名称(a、b、c…)
- HAP 体积减少约 10%-20%
- 错误堆栈不再可读(需要 mapping 文件还原)
- 社区贡献者不能直接通过阅读 release 产物理解代码
- 需要保留 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 全部开启
caseSensitiveCheck 和 useNormalizedOHMUrl 都是在编译阶段进行检查,不影响运行时性能和 HAP 体积。开启它们等于免费获得了一层"最佳实践校验"。
4. buildModeSet 至少包含 debug 和 release
这是一个几乎所有项目都会保持的默认配置。只有在需要额外的构建模式时(如 staging、beta)才扩展数组。
5. 代码文件不要进 rawfile
copyCodeResource: false 应该是默认选择。只有当你确实需要从 rawfile 动态加载代码时才开启——比如实现热更新或插件化架构。
配置即文档
最后谈一个认知层面的观点:build-profile.json5 不仅是配置文件,也是一种文档。一个新人打开项目,他看到的第一个"有信息量"的东西(除了 README)就是 build-profile.json5。通过它,你能推断出:这个应用用什么 SDK 版本?是否有多个产品变体?是否做代码混淆?支持哪些设备?
因此,配置文件的注释很重要。HarmonyKit 的配置虽然简洁,但每个关键字段都有明确的场景对应——这不是为了配置而配置,而是为了让所有协作者能在五分钟内理解项目的构建策略。
更多推荐




所有评论(0)