鸿蒙 CLI 打包实战:不用 IDE 的跨平台构建与签名
环境:Windows 11,DevEco Studio 26.0,HarmonyOS SDK 26.0.0(API 26),PowerShell 7
场景:不启动 IDE,只通过命令行完成 HAP、HSP、HAR、native 和整包的构建与签名。
本文所有结论均来自实际 CLI 构建实测。
目录
-
DevEco Studio 目录体检
-
lib\目录能否删除:改名实测 -
CLI 打包全矩阵
-
签名方案
-
踩坑清单
-
模拟器 CLI
-
GitHub 建仓与网络问题
-
总结
1. DevEco Studio 目录体检
安装目录 C:\Program Files\Huawei\DevEco Studio 的直接子目录体积:
| 目录 | 体积 | 内容 | 打包需要 |
|---|---|---|---|
sdk\default\ | 6819 MB | SDK 本体:ets/js 编译器、native 交叉链(自带 llvm+cmake)、toolchains(restool、hap-sign-tool.jar 等)、previewer | 必须 |
tools\ | 909 MB | hvigor(构建)、ohpm(包管理)、node(运行时)、emulator(模拟器)、llvm、arktsdoc 等 | 部分必须 |
lib\ | 812 MB | JetBrains IDE 平台库(app.jar 44MB、skiko 渲染、jna、pty4j、sqliteij) | 不需要 |
jbr\ | 479 MB | 内置 JDK(JetBrains Runtime) | 可不留(系统有 JDK 17/21) |
bin\ | 4 MB | IDE 启动器 devecostudio64.exe | 不用 IDE 可删 |
license\ modules\ | 2 MB | IDE 许可/模块 | 可删 |
tools\ 子目录:
| 目录 | 体积 | 内容 | 打包需要 |
|---|---|---|---|
hvigor\ | 227 MB | 构建系统(hvigorw),纯 node | 必须留 |
llvm\ | 187 MB | IDE 的 llvm(调试 C++ 用) | 可删(SDK native 自带) |
emulator\ | 184 MB | 模拟器 CLI(Emulator.exe) | 要模拟器就留 |
node\ | 98 MB | 自带 node.exe | 必须留(hvigor/ohpm 用它) |
ohpm\ | 86 MB | 包管理器 | 必须留 |
arktsdoc\ | 76 MB | ArkTS 文档生成器 | 可删 |
UxTestService\ | 31 MB | UI 自动测试服务 | 可删 |
profiler\ | 20 MB | 性能分析器 | 可删 |
dumpParser\ | 少量 | dump 解析 | 可删 |
已执行的安全删除(打包链零引用,约 127MB):tools\arktsdoc\、tools\UxTestService\、tools\profiler\、tools\dumpParser\。
删后实测:hvigorw --version = 6.26.8,ohpm --version = 26.0.0.630。
2. lib\ 目录能否删除:改名实测
2.1 证据链
-
文本扫描:打包链(hvigor/ohpm/sdk/emulator)配置文件中,对
Studio\lib的引用为零。 -
PE 导入表:
Emulator.exe的 45 个 DLL 导入全部来自自带目录(Qt5/ffmpeg/glfw/vulkan)和系统库,没有引用lib\下的 DLL。 -
改名实测:
lib→lib.bak,清空 build 目录,全矩阵重建。
| 类型 | lib 存在时 | lib 改名后 |
|---|---|---|
| HAP(ArkTS) | BUILD SUCCESSFUL 19.6s | BUILD SUCCESSFUL 13.2s,HAP 17,006 B 逐字节相同 |
| 多模块整包(含 native) | BUILD SUCCESSFUL | BUILD SUCCESSFUL 10.5s,86 tasks 全执行 |
2.2 结论
lib\(812MB)是纯 IDE 本体,删除对打包链零影响。唯一代价是无法再启动 DevEco IDE,需要时重装即可。
删除前确认模拟器镜像在别处:%LOCALAPPDATA%\Huawei\Sdk\system-image,与 lib 无关。
3. CLI 打包全矩阵
3.1 环境变量
DEVECO_SDK_HOME 指向 sdk 根目录,不是 sdk\default。指错会报:
text
ERROR 00303312 Configuration Error: Cannot find the corresponding SDK version
bash
DEVECO_SDK_HOME="C:\Program Files\Huawei\DevEco Studio\sdk" \ "C:\Program Files\Huawei\DevEco Studio\tools\hvigor\bin\hvigorw.bat" <task> --no-daemon
3.2 最小工程结构(HAP)
text
testapp/
├── AppScope/
│ ├── app.json5
│ └── resources/base/element|media/
├── build-profile.json5
├── hvigorfile.ts
├── hvigor/hvigor-config.json5
├── oh-package.json5
└── entry/
├── build-profile.json5
├── hvigorfile.ts
├── oh-package.json5
├── obfuscation-rules.txt
└── src/main/
├── module.json5
├── ets/entryability/EntryAbility.ets
├── ets/pages/Index.ets
└── resources/base/...
构建任务:
| 任务 | 产物 |
|---|---|
assembleHap | entry\build\default\outputs\default\entry-default-unsigned.hap |
assembleApp | build\outputs\default\xxx-default-unsigned.app |
assembleHsp | HSP 模块独立打包 |
3.3 多模块
HAR(静态库)
-
library/hvigorfile.ts用harTasks -
入口必须在
src/main/ets/Index.ets -
oh-package.json5的main写"./src/main/ets/Index.ets" -
module.json5里不允许deliveryWithInstall/installationFree
HSP(共享包)
-
shared/hvigorfile.ts用hspTasks -
module.json5的type为shared -
入口同样在
src/main/ets
Native C++(napi)
不是独立模块,代码放在 entry 模块内:
-
entry/src/main/cpp/CMakeLists.txt+napi_init.cpp -
entry/build-profile.json5的buildOption.externalNativeOptions.path指向 CMakeLists -
entry/hvigorfile.ts用hapTasks即可 -
产物:
libs/arm64-v8a/libentry.so打进 HAP -
import 写法:
import testNapi from 'libentry.so'(编译器 WARN "module not verified" 是正常现象)
模块间依赖
根 build-profile.json5 的 modules 列表全注册;entry 的 oh-package.json5 声明:
json5
"dependencies": {
"library": "file:../library",
"shared": "file:../shared"
}
先 ohpm install(生成 entry/oh_modules 软链)再构建。import 用 from 'library'。
3.4 实测命令
bash
# 全多模块打包(含 native、HAR、HSP) cd testapp && DEVECO_SDK_HOME="...\sdk" hvigorw assembleHap --no-daemon # 整包 DEVECO_SDK_HOME="...\sdk" hvigorw assembleApp --no-daemon
产物实测(lib 改名状态下):
| 产物 | 大小 |
|---|---|
HAP(含 libs/arm64-v8a/libentry.so + ets/modules.abc) | 1,284,432 B |
| App | 458,243 B |
| app-symbol.zip | 424,017 B |
| shared-default-unsigned.hsp | 4,746 B |
4. 签名方案
4.1 材料
全部在 SDK:sdk\default\openharmony\toolchains\lib\
| 文件 | 说明 |
|---|---|
OpenHarmony.p12 | 密码 123456,私钥别名 openharmony application profile debug |
OpenHarmonyProfileDebug.pem | 证书链 |
UnsgnedDebugProfileTemplate.json | provisioning profile 模板 |
4.2 为什么绕开 hvigor 签名
hvigor 内部 SignHap 的 storePassword/keyPassword 只认 IDE 加密格式(hex 密文 + material 目录密钥),明文 32 字符过不了。纯 CLI 必须绕开 hvigor 签名,直接用 jar。
4.3 两步直签
bash
JAVA="C:\Users\<用户名>\tools\jdk-17.0.20.1\bin\java.exe" TOOL="C:\Program Files\Huawei\DevEco Studio\sdk\default\openharmony\toolchains\lib\hap-sign-tool.jar" PW="12345678901234567890123456789012" # 1. 签发 provisioning profile $JAVA -jar $TOOL sign-profile -mode localSign \ -keyAlias "openharmony application profile debug" -keyPwd $PW \ -profileCertFile OpenHarmonyProfileDebug.pem \ -inFile UnsgnedDebugProfileTemplate.json -signAlg SHA256withECDSA \ -keystoreFile debug-material.p12 -keystorePwd $PW -outFile profile.p7b # 2. 签 HAP $JAVA -jar $TOOL sign-app -mode localSign \ -keyAlias "openharmony application profile debug" -keyPwd $PW \ -appCertFile OpenHarmonyProfileDebug.pem -profileFile profile.p7b \ -inFile entry-default-unsigned.hap -signAlg SHA256withECDSA \ -keystoreFile debug-material.p12 -keystorePwd $PW \ -outFile entry-signed.hap -compatibleVersion 26 -signCode 1 # 3. 验证 $JAVA -jar $TOOL verify-app -inFile entry-signed.hap \ -outCertChain cert.cer -outProfile verify.p7b
实测:签名块增加 64,602 B,verify: Verify success(Digest SHA-256 true)。
-compatibleVersion 26 对应 API 26。
4.4 适用范围
这套 SDK 自签仅用于 debug 和 OpenHarmony 生态。production 真机签名需要 AppGallery Connect 签发的正式证书(.cer + .p7b)。
5. 踩坑清单
| # | 问题 | 症状 | 解法 |
|---|---|---|---|
| 1 | SDK 路径指错 | 00303312 Cannot find SDK version | DEVECO_SDK_HOME 指 sdk 根 |
| 2 | HAR/HSP 入口位置 | Cannot find module './components/…' | 入口放 src/main/ets/Index.ets,oh-package 的 main 同步 |
| 3 | HAR module.json5 多字段 | property name must be valid | har 禁用 deliveryWithInstall / installationFree |
| 4 | native 独立模块 | Cannot find hvigor task 'assembleHap' in module | native 代码并入 entry 模块,用 hapTasks |
| 5 | release 缺混淆文件 | 00304036 rule file not found | 建空 entry/obfuscation-rules.txt |
| 6 | 签名密码过短 | storePassword length less than 32 | p12 转出设 ≥32 密码 |
| 7 | hvigor 不认明文密码 | 00303107 / 00308018 | 绕开,用 hap-sign-tool.jar 直签 |
| 8 | verify outProfile 后缀 | 11012005 Not support file | 输出名用 .p7b |
| 9 | 跨盘迁移 git | robocopy exit=1 像失败 | robocopy 退出码 0-7 都是成功 |
| 10 | git 全局代理失效 | push 连 127.0.0.1:26561 失败 | git config --global --unset http.proxy |
| 11 | GitHub 被墙 | Connection reset / CONNECT tunnel 400 | 走 SSH 443(见第 7 节) |
| 12 | Program Files 写删无权限 | Access denied | 提权子进程:Start-Process powershell -Verb RunAs -File 脚本 |
6. 模拟器 CLI
路径:C:\Program Files\Huawei\DevEco Studio\tools\emulator\Emulator.exe。PE 导入表独立,自带 Qt5/ffmpeg,不依赖根 lib。
bash
-emulator -help # 下载镜像 -install -deviceType phone -osVersion "HarmonyOS 7.0.0(26.0.0)" # 首次必须 stdin 喂 y(否则 1 秒静默退出) # 同意后写 %LOCALAPPDATA%\Huawei\Emulator26.0\.emu_config # 镜像落 %LOCALAPPDATA%\Huawei\Sdk\system-image\HarmonyOS-7.0.0\phone_all_x86\(system.img 3.5GB) -imageList / -uninstall / -screenProfileList / -deviceTypeList # 实例管理 -create <name> -deviceType <type> -osVersion <ver> [-screenProfile "Mate 90 Pro"|-storage 2~1023|-memory 2~32|-hotBoot] -list [-details] / -start [-noWindow] / -stop / -delete <name> [-force] # 设备控制 -instance <name> -rotation|-volume|-power|-shake|-foldedState|-battery|-gps|-sensor|-click|-slide|-fill|-uiLayout -screenshot -screenshotPath <p> / -logZip / -version
已知约束:
-
-create无 CPU 核数参数(只有 memory/storage)。默认内存 4GB、存储 6GB -
镜像下载进度行格式
X.X% (bytes/total bytes),每约 400KB 一行 -
GUI 里流式读输出:PS 事件回调线程无 Runspace 会崩进程,需用
Add-TypeC# 类(ConcurrentQueue)+ UI Timer 消费
7. GitHub 建仓与网络问题
7.1 建仓
bash
cd 项目目录 git init -b main git add -A && git -c user.name=xxx -c user.email=xxx commit -m "初始提交" gh repo create <仓库名> --private --source . --push --description "..." # 改公开 gh repo edit <用户名>/<仓库名> --visibility public
7.2 网络问题
| # | 现象 | 原因 | 解法 |
|---|---|---|---|
| 1 | Failed to connect to github.com:443 over proxy 127.0.0.1 | 全局 git 代理指向已失效的本地代理 | git config --global --unset http.proxy(https.proxy 一起删) |
| 2 | 删代理后 Connection was reset | HTTPS 直连被墙 | 用 SSH,remote 改 git@github.com:... |
| 3 | CONNECT tunnel failed, response 400 | gh 配置的代理不支持 git 隧道 | 弃用代理,走 SSH 443 |
7.3 SSH 443 配置
~/.ssh/config 追加:
text
Host github.com
HostName ssh.github.com
Port 443
User git
IdentityFile ~/.ssh/id_ed25519
StrictHostKeyChecking accept-new
然后:
bash
git remote set-url origin git@github.com:<用户名>/<仓库>.git
实测 443 可通,22 被墙。
7.4 跨盘移动 git 仓库
bash
robocopy 源 目标 /E /MOVE /R:2 /W:3 /NFL /NDL /NJH /NJS /NP
robocopy 退出码 0-7 都是成功,exit=1 表示有文件被复制,不是失败。
8. 总结
不用 IDE 做鸿蒙跨平台打包的要点:
-
保留:
sdk\+tools\{hvigor, ohpm, node, emulator} -
可删:
lib\(812MB)、jbr\、bin\、IDE 辅助工具(约 127MB) -
构建:
DEVECO_SDK_HOME=<sdk 根> hvigorw assembleApp --no-daemon -
签名:绕开 hvigor,用
hap-sign-tool.jar直签 -
网络:GitHub 走 SSH 443
lib\ 的删除有改名实测作为证据,不是推断。签名方案绕过了 hvigor 的加密密码限制,直接用 SDK 自带的 jar 完成。整条链路实际跑通。
本文基于实际 CLI 构建与签名验证整理。不同 DevEco Studio 版本、SDK 版本和工程结构下细节可能不同,请以实际环境为准。
更多推荐




所有评论(0)