K1 OH5.0 应用开发说明
修订记录
| 修订版本 | 修订日期 | 修订说明 |
| 001 | 2025-06-10 | 初始版本 |
| 002 | 2025-07-25 | 添加一些FAQ |
1. OpenHarmony 应用开发概述
1.1 ArkTS
ArkTS 是鸿蒙(HarmonyOS/OpenHarmony)生态的官方主力应用开发语言,基于 TypeScript(TS)扩展而来,是 TS 的超集扩展,继承 TypeScript 语法风格,强化静态类型检查(编译时检测错误,提升代码健壮性),兼容 JS/TS 生态,支持高效互操作,降低迁移门槛。
1.1.1 核心技术特性
-
声明式 UI 开发 范式
- 通过装饰器(如
@Entry、@Component)定义组件,以简洁的声明式语法构建界面逻辑 - 提供状态管理(如
@State),驱动数据变化自动更新 UI
- 通过装饰器(如
-
分布式与并发增强
- 优化并发编程 API,支持多线程任务调度(如 Taskpool 机制),提升跨设备协同性能
- 为“一次开发,多端部署”提供底层支持,适配手机、平板、车机等全场景设备
-
性能与稳定性优化
- 静态类型约束减少运行时类型检查,提高执行效率
- 强制属性显式初始化(如类成员变量),避免未定义错误导致的运行时崩溃
1.2. ArkUI
ArkUI(方舟 UI 框架)是华为为 HarmonyOS/OpenHarmony 生态系统构建的声明式 UI 开发框架,专注于实现高效、高性能的跨设备应用界面开发。基于 ArkTS 语言扩展(TypeScript 超集),通过组件化、状态驱动等机制简化 UI 构建逻辑,提供极简的 UI 语法(如装饰器 @Component),开发者通过声明式描述界面结构而非命令式操作。

1.2.1. 核心技术特性
-
高性能渲染架构
- 优化 UI 更新机制:将 Diff 算法从树形结构对比升级为单节点函数式更新,大幅提升渲染效率
- 统一渲染引擎保障流畅动效,减少主线程卡顿
-
逻辑与 UI 解耦
- 通过数据双向绑定简化状态管理,跨端开发代码量减少 40% 以上
- 支持状态管理(如
@State、@Link),实现数据变化自动驱动 UI 刷新
-
多形态组件库
- 提供丰富内置组件(文本、按钮、列表等)及布局能力,覆盖基础界面到复杂交互场景
- 支持自定义组件开发,满足业务定制化需求
1.3 Ark 运行时(方舟运行时)
Ark 运行时(又称方舟运行时)是 HarmonyOS/OpenHarmony 生态中支撑 ArkTS/JS/TS 语言执行的核心引擎,负责字节码运行、内存管理及跨语言互调等关键能力。
1.3.1 核心架构组成
-
核心子系统(Core Subsystem)
- 提供基础运行库,支撑字节码文件解析(File 组件)、调试工具链(Tooling 组件)及系统调用适配(Base 库)
-
执行子系统(Execution Subsystem)
- 包含字节码解释器、内联缓存优化机制,实现高效执行方舟字节码(
.abc文件)
- 包含字节码解释器、内联缓存优化机制,实现高效执行方舟字节码(
-
编译器子系统(Compiler Subsystem)
- 支持 AOT(预编译优化)、JIT(动态编译实验阶段)及基于 IR 的编译框架,提升代码执行效率
-
运行时子系统(Runtime Subsystem)
- 内存管理:CMS-GC 垃圾回收器实现并发标记与部分内存压缩
- 跨语言接口:通过 Node-AP I 支持 TS/JS/C++ 等多语言混合开发
1.3.2 关键技术特性
-
多模式执行引擎
- 同时支持解释执行、AOT 预编译及实验性 JIT 动态编译,平衡启动速度与运行效率
-
高性能内存管理
- 采用并行标记的 CMS-GC 算法,减少暂停时间;支持部分内存压缩,优化内存碎片
-
分布式调试支持
- 内置 Debugger 工具链,实现跨设备协同开发时的实时诊断与性能分析
-
标准库兼容性
- 完整实现 ECMAScript 规范,提供高效容器库(如 Map/Set),保障 JS/TS 生态兼容
2. 开发环境搭建(windows)
2.1 DevEco Studio 安装配置
- 下载工具:点我下载 DevEcoStudio5.0.5.310,DevEco Studio 是开发 OpenHarmony 应用程序的专用 IDE
- 双击下载的
deveco-studio-xxxx.exe,进入 DevEco Studio 安装向导,默认安装于C:\Program Files路径下,也可以安装到指定位置(**注意:**不要出现中文或特殊字符),然后单击NEXT
2.2 SDK 工具链配置
OpenHarmony 的 SDK 是专为 OpenHarmony 系统设计的软件开发工具包,它能够提供开发原生应用所需的基础能力和工具集。所以,我们需要下载并且配置好 SDK 才能够进行应用开发。
2.2.1 Public SDK 与 Full SDK
在 OpenHarmony 中,Public SDK 与 Full SDK 是面向不同开发场景的工具包,其核心差异如下:
- API 权限
| 类型 | 权限说明 |
| Public SDK | 提供给普通应用开发者使用,仅包含开放API,不涉及系统敏感权限(如@ohos.app.ability.abilityManager、蓝牙控制等高权限接口) |
| Full SDK | 面向 OEM 厂商及系统应用开发者,包含所有系统级 API(包括需要高权限调用的接口) |
- 获取与部署方式
| 类型 | 获取途径 |
| Public SDK | 在 DevEco Studio 中下载,开发者无需额外操作 |
| Full SDK | 需手动单独下载(从 OpenHarmony 镜像站点或编译源码获取),并替换 Public SDK |
- 适用场景
| 场景 | 推荐SDK | 原因 |
| 普通三方应用开发 | Public SDK | 满足基础功能需求,避免权限滥用风险 |
| 系统级应用(如Launcher) | Full SDK | 需调用高权限接口实现系统管理、硬件控制等能力 |
| 依赖未开放API的功能 | Full SDK | 如使用mediaLibrary深度媒体处理或定制系统服务 |
2.2.2 下载 Public SDK
DevEco Studio 提供开箱即用的开发体验,将 HarmonyOS SDK、Node.js、Hvigor、OHPM、模拟器平台等进行合一打包,简化 DevEco Studio 安装配置流程。
HarmonyOS SDK 已嵌入 DevEco Studio 中,无需额外下载配置。但 OpenHarmony 的 SDK 没有集成,如需进行 OpenHarmony 应用开发,可通过 File -> Settings -> OpenHarmony SDK 页签下载 OpenHarmony SDK。

上图中,下载了 API10/API11/API12 的 3 个 SDK,保存在 Z:\workspace\ohsdk 的路径下
2.2.3 替换 Full SDK
- 下载 K1 OH5.0 的 Full SDK,点我下载,目前 K1 OH5.0 仅支持 API12,系统支持 windows/macos/ubuntu 等,按照自己的开发机系统来下载。

- 下载了 Full SDK 后,进行解压,并将 Public SDK 中对应的目录替换掉即可。
2.3 真机调试
通过 hdc 成功连接开发设备后,如下图,Deveco Studio 右上角会显示连接的设备,以及一些运行调试的按键。

编译好的应用可以点击绿色的箭头在真机运行调试。hdc 的安装与使用方法请参照 K1 OH5.0 系统调试说明 的 1.2 章节进行。
3. HelloWorld
3.1 创建工程
- 双击运行
Deveco Studio应用,进入配置导入页面,选择不导入任何配置(第一次是没有项目和配置的) - 如下图,根据工程创建向导,选择创建
Application应用服务或Atomic Service元服务。再选择需要的 Ability 工程模板,然后单击 Next。

- 在工程配置页面(如下图),需要根据向导配置工程的基本信息
Project name:工程的名称,可以自定义,由大小写字母、数字和下划线组成。Bundle name:标识应用的包名,用于标识应用的唯一性。Save location:工 程文件本地存储路径,由大小写字母、数字和下划线等组成,不能包含中文字符。Compatible SDK:兼容的最低 API Version。Device type:该工程模板支持的设备类型。

- 单击 Finish,工具会自动生成示例代码和相关资源,等待工程创建完成
3.2 项目结构

AppScope->app.json5: 应用的全局配置信息entry:OpenHarmony工程模块,编译构建生成一个 HAP 包entry->src->main->ets:用于存放 ArkTS 源代码entry->src->main->ets->entryability:应用/服务的入口。entry->src->main->ets->entrybackupability:应用提供扩展的备份恢复能力。entry->src->main->ets->pages:应用/服务包含的页面。entry->src->main->resources:用于存放应用/服务所用到的资源文件,如图形、多媒体、字符串、布局文件等entry->src->main->module.json5:模块配置文件。主要包含 HAP 包的配置信息、应用/服务在具体设备上的配置信息以及应用/服务的全局配置信息。entry->build-profile.json5: 当前的模块信息 、编译信息配置项,包括 buildOption、targets 配置等。entry->hvigorfile.ts: 模块级编译构建任务脚本。entry->obfuscation-rules.txt: 混淆规则文件。混淆开启后,在使用 Release 模式进行编译时,会对代码进行编译、混淆及压缩处理,保护代码资产。entry->oh-package.json5: 用来描述包名、版本、入口文件(类型声明文件)和依赖项等信息。oh_modules: 用于存放三方库依赖信息。build-profile.json5: 工程级配置信息,包括签名signingConfigs、产品配置 products 等。其中 products 中可配置当前运行环境,默认为 HarmonyOS。oh-package.json5: 主要用来描述全局配置,如:依赖覆盖(overrides)、依赖关系重写(overrideDependencyMap)和参数化配置(parameterFile)等。
3.3 页面编写
点击 entry -> src -> main -> ets -> pages,打开 Index.ets 文件,进行页面的编写。
3.4 修改 build-profile.json5
应用根目录的 build-profile.json5 中,将
"products": [
{
"name": "default",
"signingConfig": "default",
"compatibleSdkVersion": "5.0.0(12)",
"runtimeOS": "HarmonyOS",
"buildOption": {
"strictMode": {
"caseSensitiveCheck": true,
"useNormalizedOHMUrl": true
}
}
}
],
修改为
"products": [
{
"name": "default",
"signingConfig": "default",
"compileSdkVersion": 12,
"compatibleSdkVersion": 12,
"runtimeOS": "OpenHarmony"
}
],
主要修改点包括:
runtimeOS改为OpenHarmony- 添加
compileSdkVersion - 修改
compatibleSdkVersion的格式
3.5. 签名 (普通签名)
点击 File -> Project Structure -> Signing Configs,进入签名页面,进行如下设置,点击 Apply,再点击 OK 即可。

注意:上面绿框标注的 Support HarmonyOS 不用勾选
3.6 编译
点击 Build -> Build Hap(s)/APP(s) -> Build Hap(s) 进行编译,Build Output 中有如下输出,说明编译成功。
> hvigor Finished :entry:default@SignHap... after 3 ms
> hvigor Finished :entry:assembleHap... after 1 ms
> hvigor BUILD SUCCESSFUL in 35 s 204 ms
Process finished with exit code 0
Build Analyzer results available
3.7 真机运行
点击右上角的运行按键,进行安装和运行。

4. 系统应用编译安装
以 launcher 为例说明系统应用编译安装过程(注意:编译系统应用需要 Full SDK)。
4.1 打开应用工程
将 applications/standard/launcher 文件夹拷贝到 D 盘(注意:目录不要有中文,可能会有问题)
Deveco Studio 中,点击 File -> Open,选择 launcher 文件夹打开
4.2 编译
点击 Build -> Build Hap(s)/APP(s) -> Build Hap(s) 进行编译,Build Output 中有如下输出,说明编译成功。
> hvigor Finished :pad_launcher:assembleHap... after 1 ms
> hvigor Finished :phone_launcher:default@SignHap... after 3 s 484 ms
> hvigor Finished :phone_launcher:assembleHap... after 1 ms
> hvigor BUILD SUCCESSFUL in 4 min 16 s 555 ms
Process finished with exit code 0
Build Analyzer results available
launcher 编译完成后,会生成 2 个 hap:
launcher\product\phone\build\default\outputs\default\phone_launcher-default-signed.haplauncher\feature\settings\build\default\outputs\default\launcher_settings-phone_launcher-default-signed.hap
4.3 安装
系统应用安装没办法像非系统应用那样直接点击安装按键,需要执行一系列操作,可以写一个脚本一键安装,如下:
hdc shell mount -o rw,remount /
hdc shell rm -rf /system/app/com.ohos.launcher/*
hdc shell rm -rf /data/*
hdc file send D:\HAP_CODE\launcher\product\phone\build\default\outputs\default\phone_launcher-default-signed.hap /system/app/com.ohos.launcher/Launcher.hap
hdc file send D:\HAP_CODE\launcher\feature\settings\build\default\outputs\default\launcher_settings-phone_launcher-default-signed.hap /system/app/com.ohos.launcher/Launcher_Settings.hap
hdc shell rm -rf /data/*
hdc shell sync /system/bin/udevadm trigger
pause
hdc shell reboot
5. 系统签名
为普通应用赋予系统权限,需使用 Full SDK 进行系统签名。具体流程如下:
5.1 签名工具介绍
签名工具的路径在 ohsdk\12\toolchains\lib,如下:
fuqiang@snode1:~/workspace/ohsdk/12/toolchains/lib$ tree
.
├── app_check_tool.jar
├── app_packing_tool.jar
├── app_unpacking_tool.jar
├── hap-sign-tool.jar
├── OpenHarmony.p12
├── OpenHarmonyProfileDebug.pem
├ ── OpenHarmonyProfileRelease.pem
├── UnsgnedDebugProfileTemplate.json
└── UnsgnedReleasedProfileTemplate.json
0 directories, 9 files
5.2 修改配置
修改 UnsgnedDebugProfileTemplate.json 文件和 UnsgnedReleasedProfileTemplate.json 文件的应用包名、权限、应用类型,如下:
"bundle-name":"com.example.myapplication",
"apl":"normal",
"app-feature":"hos_normal_app"
修改为:
"bundle-name":"com.example.myapplication",
"apl":"system_core",
"app-feature":"hos_system_app"
5.3. 生成 .``p12
java -jar hap-sign-tool.jar generate-keypair -keyAlias "ohos-app" -keyAlg "ECC" -keySize "NIST-P-256" -keystoreFile "app.p12" -keyPwd "ohos123456" -keystorePwd "ohos123456"
5.4 生成 .``csr
java -jar hap-sign-tool.jar generate-csr -keyAlias "ohos-app" -keyPwd "ohos123456" -subject "C=CN,O=OpenHarmony,OU=OpenHarmony Team,CN=OpenHarmony Application Release" -signAlg "SHA256withRSA" -keystoreFile "app.p12" -keystorePwd "ohos123456" -outFile "app.csr"
5.5 生成 .``cer
keytool -gencert -alias "OpenHarmony Application CA" -infile app.csr -outfile app-release.cer -keystore OpenHarmony.p12 -sigalg SHA384withECDSA -storepass 123456 -ext KeyUsage:"critical=digitalSignature" -validity 36500 -rfc
5.6 生成 .``p7b
java -jar hap-sign-tool.jar sign-profile -keyAlias "openharmony application profile release" -signAlg "SHA256withECDSA" -mode "localSign" -profileCertFile "OpenHarmonyProfileRelease.pem" -inFile "UnsgnedReleasedProfileTemplate.json" -keystoreFile "OpenHarmony.p12" -outFile "app-release-profile.p7b" -keyPwd "123456" -keystorePwd "123456"
5.7 配置 Deveco Studio 的签名
Store file(*.p12): app.12
keyAlias: ohos-app
Store Password: ohos123456
key Password: ohos123456
Profile file(*.p7b): app-release-profile.p7b
Certpath file(*.cer): app-release.cer
6. NAPI(Native API) 应用
NAPI 的调用有 2 种方式:
- 将 NAPI 的实现打包于 HAP 应用中,适用于应用开发者
- 将 NAPI 的实现集成在系统中,作为系统能力提供,适用于系统开发者
下面对 2 种方式分别说明:
6.1 NAPI 打包在 HAP
6.1.1. DevEco Studio 支持 RISC-V 编译
DevEco Studio 本身的配置文件未添加 RISC-V 配置,需要手动更改,更改位置在 DevEco Studio 的安装目录下的 tools/hvigor 中,具体修改如下:
diff --git a/hvigor-ohos-plugin/res/schemas/hvigorfile-configuration/har-module-schema.json b/hvigor-ohos-plugin/res/schemas/hvigorfile-configuration/har-module-schema.json
index d53b7fc..72b4e28 100644
--- a/hvigor-ohos-plugin/res/schemas/hvigorfile-configuration/har-module-schema.json
+++ b/hvigor-ohos-plugin/res/schemas/hvigorfile-configuration/har-module-schema.json
@@ -29,7 +29,8 @@
"enum": [
"arm64-v8a",
"armeabi-v7a",
- "x86_64"
+ "x86_64",
+ "riscv64"
]
},
"minItems": 1
diff --git a/hvigor-ohos-plugin/res/schemas/hvigorfile-configuration/module-schema.json b/hvigor-ohos-plugin/res/schemas/hvigorfile-configuration/module-schema.json
index 53d5182..87cae34 100644
--- a/hvigor-ohos-plugin/res/schemas/hvigorfile-configuration/module-schema.json
+++ b/hvigor-ohos-plugin/res/schemas/hvigorfile-configuration/module-schema.json
@@ -33,7 +33,8 @@
"enum": [
"arm64-v8a",
"armeabi-v7a",
- "x86_64"
+ "x86_64",
+ "riscv64"
]
},
"minItems": 1
diff --git a/hvigor-ohos-plugin/res/schemas/ohos-har-module-build-profile-schema.json b/hvigor-ohos-plugin/res/schemas/ohos-har-module-build-profile-schema.json
index 9269b9b..e63bee8 100644
--- a/hvigor-ohos-plugin/res/schemas/ohos-har-module-build-profile-schema.json
+++ b/hvigor-ohos-plugin/res/schemas/ohos-har-module-build-profile-schema.json
@@ -56,7 +56,8 @@
"enum": [
"arm64-v8a",
"armeabi-v7a",
- "x86_64"
+ "x86_64",
+ "riscv64"
]
},
"minItems": 1
diff --git a/hvigor-ohos-plugin/res/schemas/ohos-module-build-profile-schema.json b/hvigor-ohos-plugin/res/schemas/ohos-module-build-profile-schema.json
index 76656c1..9c23f7a 100644
--- a/hvigor-ohos-plugin/res/schemas/ohos-module-build-profile-schema.json
+++ b/hvigor-ohos-plugin/res/schemas/ohos-module-build-profile-schema.json
@@ -204,7 +204,8 @@
"enum": [
"arm64-v8a",
"armeabi-v7a",
- "x86_64"
+ "x86_64",
+ "riscv64"
]
},
"minItems": 1
diff --git a/hvigor-ohos-plugin/res/schemas/ohos-project-build-profile-schema.json b/hvigor-ohos-plugin/res/schemas/ohos-project-build-profile-schema.json
index 0619757..d090098 100644
--- a/hvigor-ohos-plugin/res/schemas/ohos-project-build-profile-schema.json
+++ b/hvigor-ohos-plugin/res/schemas/ohos-project-build-profile-schema.json
@@ -233,7 +233,8 @@
"enum": [
"arm64-v8a",
"armeabi-v7a",
- "x86_64"
+ "x86_64",
+ "riscv64"
]
},
"minItems": 1
diff --git a/hvigor-ohos-plugin/src/enum/cpu-abi-enum.d.ts b/hvigor-ohos-plugin/src/enum/cpu-abi-enum.d.ts
index b9437e3..1aee1a5 100644
--- a/hvigor-ohos-plugin/src/enum/cpu-abi-enum.d.ts
+++ b/hvigor-ohos-plugin/src/enum/cpu-abi-enum.d.ts
@@ -1,7 +1,8 @@
export declare enum CpuAbiEnum {
ARM64_V8A = "aarch64-linux-ohos",
ARMEABI_V7A = "arm-linux-ohos",
- X86_64 = "x86_64-linux-ohos"
+ X86_64 = "x86_64-linux-ohos",
+ RISCV64 = "riscv64-linux-ohos"
}
/**
* 为CpuAbiEnum枚举类型附加方法
diff --git a/hvigor-ohos-plugin/src/enum/cpu-abi-enum.js b/hvigor-ohos-plugin/src/enum/cpu-abi-enum.js
index be106b9..3048ea7 100644
--- a/hvigor-ohos-plugin/src/enum/cpu-abi-enum.js
+++ b/hvigor-ohos-plugin/src/enum/cpu-abi-enum.js
@@ -1 +1 @@
-"use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.CpuAbiEnum=void 0;const ohos_logger_js_1=require("../utils/log/ohos-logger.js"),_log=ohos_logger_js_1.OhosLogger.getLogger("CpuAbiEnum");var CpuAbiEnum;!function(o){o.ARM64_V8A="aarch64-linux-ohos",o.ARMEABI_V7A="arm-linux-ohos",o.X86_64="x86_64-linux-ohos"}(CpuAbiEnum=exports.CpuAbiEnum||(exports.CpuAbiEnum={})),function(o){o.getCpuType=r=>{switch(r){case"arm64-v8a":return o.ARM64_V8A;case"armeabi-v7a":return o.ARMEABI_V7A;case"x86_64":return o.X86_64;default:return _log._buildError(`Unknown abiFilter ${r}`)._solution("Value should be one of: 'arm64-v8a', 'armeabi-v7a', 'x86_64'")._printErrorAndExit(),o.ARM64_V8A}}}(CpuAbiEnum=exports.CpuAbiEnum||(exports.CpuAbiEnum={}));
\ No newline at end of file
+"use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.CpuAbiEnum=void 0;const ohos_logger_js_1=require("../utils/log/ohos-logger.js"),_log=ohos_logger_js_1.OhosLogger.getLogger("CpuAbiEnum");var CpuAbiEnum;!function(o){o.ARM64_V8A="aarch64-linux-ohos",o.ARMEABI_V7A="arm-linux-ohos",o.X86_64="x86_64-linux-ohos",o.RISCV64="riscv64-linux-ohos"}(CpuAbiEnum=exports.CpuAbiEnum||(exports.CpuAbiEnum={})),function(o){o.getCpuType=r=>{switch(r){case"arm64-v8a":return o.ARM64_V8A;case"armeabi-v7a":return o.ARMEABI_V7A;case"x86_64":return o.X86_64;case"riscv64":return o.RISCV64;default:return _log._buildError(`Unknown abiFilter ${r}`)._solution("Value should be one of: 'arm64-v8a', 'armeabi-v7a', 'x86_64', 'riscv64'")._printErrorAndExit(),o.ARM64_V8A}}}(CpuAbiEnum=exports.CpuAbiEnum||(exports.CpuAbiEnum={}));
\ No newline at end of file
diff --git a/hvigor-ohos-plugin/src/tasks/common/clean.js b/hvigor-ohos-plugin/src/tasks/common/clean.js
index 62ed2e4..01a0e37 100644
--- a/hvigor-ohos-plugin/src/tasks/common/clean.js
+++ b/hvigor-ohos-plugin/src/tasks/common/clean.js
@@ -1 +1 @@
-"use strict";var __createBinding=this&&this.__createBinding||(Object.create?function(e,t,r,i){void 0===i&&(i=r);var s=Object.getOwnPropertyDescriptor(t,r);s&&!("get"in s?!t.__esModule:s.writable||s.configurable)||(s={enumerable:!0,get:function(){return t[r]}}),Object.defineProperty(e,i,s)}:function(e,t,r,i){void 0===i&&(i=r),e[i]=t[r]}),__setModuleDefault=this&&this.__setModuleDefault||(Object.create?function(e,t){Object.defineProperty(e,"default",{enumerable:!0,value:t})}:function(e,t){e.default=t}),__importStar=this&&this.__importStar||function(e){if(e&&e.__esModule)return e;var t={};if(null!=e)for(var r in e)"default"!==r&&Object.prototype.hasOwnProperty.call(e,r)&&__createBinding(t,e,r);return __setModuleDefault(t,e),t},__importDefault=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(exports,"__esModule",{value:!0}),exports.Clean=void 0;const fs=__importStar(require("fs")),os_1=__importDefault(require("os")),path_1=__importDefault(require("path")),hvigor_1=require("@ohos/hvigor"),hvigor_common_1=require("@ohos/hvigor-common"),fs_extra_1=__importDefault(require("fs-extra")),build_directory_const_js_1=require("../../const/build-directory-const.js"),ohos_plugin_id_js_1=require("../../plugin/common/ohos-plugin-id.js"),inject_util_js_1=require("../../utils/inject-util.js"),ohos_logger_js_1=require("../../utils/log/ohos-logger.js"),process_utils_js_1=require("../../utils/process-utils.js"),task_util_js_1=require("../../utils/task-util.js"),validator_store_js_1=require("../../utils/validate/validator-store.js"),global_project_data_service_js_1=require("../service/global-project-data-service.js"),module_task_service_js_1=require("../service/module-task-service.js"),task_names_js_1=require("./task-names.js");class Clean extends hvigor_1.DefaultTask{constructor(e,t){super(e,task_names_js_1.TaskNames.CommonTask.CLEAN),this._logger=ohos_logger_js_1.OhosLogger.getLogger(Clean.name),this.nativeClean=e=>{if(!e)return;const t=new process_utils_js_1.ProcessUtils;let r;if(!(this._taskService instanceof module_task_service_js_1.ModuleTaskService))return;const i=path_1.default.resolve(this._taskService.getModuleModel().getProjectDir(),".cxx");if(!fs.existsSync(i))return;const s=[];this.getArchDirectories(i,s,this._taskService);const o=e.getSdkToolchainsDir();if(void 0!==o){const e=path_1.default.dirname(o);r=path_1.default.resolve(e,"native/build-tools/cmake/bin/ninja.exe")}const a=[];for(const e of s){const i=path_1.default.resolve(e,"CMakeCache.txt"),s=path_1.default.resolve(e,"build.ninja"),o=path_1.default.resolve(e,"rules.ninja"),n=path_1.default.resolve(e,"CMakeFiles","rules.ninja");if(fs.existsSync(i)&&fs.existsSync(s)&&(fs.existsSync(o)||fs.existsSync(n))){if(void 0!==r&&fs.existsSync(r)){const i=[];i.push(r),i.push("-C"),i.push(e),i.push("clean"),this.tryCatchExecute(i,a,e,t)}fs.existsSync(i)&&fs.unlinkSync(i)}}if(a.length>0){let e="Delete the following directories that are no longer needed:";for(const t of a)e=e.concat(os_1.default.EOL,t);this._logger.warn(e)}},this.tryCatchExecute=(e,t,r,i)=>{try{i.executeSync(e)}catch(e){t.push(r)}},this.getArchDirectories=(e,t,r)=>{for(const i of r.getProjectModel().getProductNames())for(const s of r.getTargets()){const r=path_1.default.resolve(e,i,s.getTargetName(),(0,task_util_js_1.getBuildModeName)());this.pushArchDirectories(r,t)}},this.registryAction=()=>async()=>{if(await this.terminateWorkerPool(),await this.clean(path_1.default.resolve(this._taskService.getProjectModel().getProjectDir(),"build")),this.resetRemoteHspCache(),this._taskService instanceof module_task_service_js_1.ModuleTaskService){const e=this._taskService.getModuleModel();if(!e)return;await this.clean(path_1.default.resolve(e.getProjectDir(),"build"),path_1.default.resolve(e.getProjectDir(),".test"))}},this.clean=async(e,t)=>{var r;let i=!1;i||(i=this.rmdirSyncWithBuildDir(e)),t&&(i||(i=this.rmdirSyncWithBuildDir(t)));const s=inject_util_js_1.InjectUtil.getBuildCacheParentDir(e,path_1.default.join(hvigor_1.hvigorCore.getProject().getName(),e.substring(hvigor_1.hvigorCore.getProject().getNodeDir().length)));if(s!==e&&(i||(i=this.rmdirSyncWithBuildDir(s)),(0,hvigor_common_1.isCI)())){const e=path_1.default.join(path_1.default.dirname(s),build_directory_const_js_1.BuildDirConst.CPP_OUTPUT);i||(i=this.rmdirSyncWithBuildDir(e)),i||this._logger.debug("CI scenario cleared .cxx dir.")}if(i&&this._logger._buildError(`Unable to delete ${e}. some files may be opened by another program.`)._printErrorAndExit(),"project"===this.node.classKind)return;const o=null===(r=this._taskService.getProjectModel().getProject().getPluginById(ohos_plugin_id_js_1.OhosPluginId.OHOS_APP_PLUGIN).getTaskService())||void 0===r?void 0:r.getSdkInfo();this.nativeClean(o)},this.terminateWorkerPool=async()=>{this.getWorkerPool().isActive()?(this._logger.debug("clean: Start terminating worker pool."),await this.getWorkerPool().terminate(),this._logger.debug("clean: Terminating worker pool finished."),hvigor_1.TcbStore.clear(),validator_store_js_1.ValidatorStore.clear()):this._logger.debug("clean: Worker pool is inactive.")},this.rmdirSyncWithBuildDir=e=>{let t=!1;return fs.existsSync(e)&&(t=this.rmdirSync(e,!1)),t&&this._logger._buildError(`Unable to delete ${e}. some files may be opened by another program.`)._printErrorAndExit(),t},this.rmdirSync=(e,t)=>{fs.readdirSync(e).forEach((r=>{const i=path_1.default.resolve(e,r),s=fs.lstatSync(i);if(s.isFile()||s.isSymbolicLink())try{fs.unlinkSync(i)}catch(e){hvigor_1.MetricFactory.createLogEvent(e.message,hvigor_1.MetricLogType.DEBUG),hvigor_1.MetricFactory.createLogEvent(`Cannot delete ${i}. The file may be opened by another program.`,hvigor_1.MetricLogType.WARN),this._logger.debug(e.message),this._logger.warn(`Cannot delete ${i}. The file may be opened by another program.`),t=!0}else s.isDirectory()&&(t=this.rmdirSync(i,t))}));try{let r=!0;if(!fs.existsSync(e))return t;fs.readdirSync(e).forEach((t=>{const i=path_1.default.resolve(e,t);fs.existsSync(i)&&(r=!1)})),r&&fs_extra_1.default.removeSync(e)}catch(r){hvigor_1.MetricFactory.createLogEvent(r.message,hvigor_1.MetricLogType.DEBUG),hvigor_1.MetricFactory.createLogEvent(`Unable to delete ${e}. A file may be open by another program.`,hvigor_1.MetricLogType.WARN),this._logger.debug(r.message),this._logger.warn(`Unable to delete ${e}. A file may be open by another program.`),t=!0}return t},this._taskService=t}pushArchDirectories(e,t){if(!fs.existsSync(e)||!this.isDirectory(e))return;const r=fs.readdirSync(e);for(const i of r){const r=path_1.default.join(e,i);if("arm64-v8a"===i||"armeabi-v7a"===i||"x86_64"===i){if(!this.isDirectory(r))continue;t.push(r)}}}isDirectory(e){try{return fs.readdirSync(e),!0}catch(e){return!1}}resetRemoteHspCache(){var e;global_project_data_service_js_1.GlobalProjectDataService.getInstance().resetRemoteHspCache(),null===(e=global_project_data_service_js_1.GlobalProjectDataService.getInstance().getIntegratedHspUtils())||void 0===e||e.resetIntegratedHspCache()}}exports.Clean=Clean;
\ No newline at end of file
+"use strict";var __createBinding=this&&this.__createBinding||(Object.create?function(e,t,r,i){void 0===i&&(i=r);var s=Object.getOwnPropertyDescriptor(t,r);s&&!("get"in s?!t.__esModule:s.writable||s.configurable)||(s={enumerable:!0,get:function(){return t[r]}}),Object.defineProperty(e,i,s)}:function(e,t,r,i){void 0===i&&(i=r),e[i]=t[r]}),__setModuleDefault=this&&this.__setModuleDefault||(Object.create?function(e,t){Object.defineProperty(e,"default",{enumerable:!0,value:t})}:function(e,t){e.default=t}),__importStar=this&&this.__importStar||function(e){if(e&&e.__esModule)return e;var t={};if(null!=e)for(var r in e)"default"!==r&&Object.prototype.hasOwnProperty.call(e,r)&&__createBinding(t,e,r);return __setModuleDefault(t,e),t},__importDefault=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(exports,"__esModule",{value:!0}),exports.Clean=void 0;const fs=__importStar(require("fs")),os_1=__importDefault(require("os")),path_1=__importDefault(require("path")),hvigor_1=require("@ohos/hvigor"),hvigor_common_1=require("@ohos/hvigor-common"),fs_extra_1=__importDefault(require("fs-extra")),build_directory_const_js_1=require("../../const/build-directory-const.js"),ohos_plugin_id_js_1=require("../../plugin/common/ohos-plugin-id.js"),inject_util_js_1=require("../../utils/inject-util.js"),ohos_logger_js_1=require("../../utils/log/ohos-logger.js"),process_utils_js_1=require("../../utils/process-utils.js"),task_util_js_1=require("../../utils/task-util.js"),validator_store_js_1=require("../../utils/validate/validator-store.js"),global_project_data_service_js_1=require("../service/global-project-data-service.js"),module_task_service_js_1=require("../service/module-task-service.js"),task_names_js_1=require("./task-names.js");class Clean extends hvigor_1.DefaultTask{constructor(e,t){super(e,task_names_js_1.TaskNames.CommonTask.CLEAN),this._logger=ohos_logger_js_1.OhosLogger.getLogger(Clean.name),this.nativeClean=e=>{if(!e)return;const t=new process_utils_js_1.ProcessUtils;let r;if(!(this._taskService instanceof module_task_service_js_1.ModuleTaskService))return;const i=path_1.default.resolve(this._taskService.getModuleModel().getProjectDir(),".cxx");if(!fs.existsSync(i))return;const s=[];this.getArchDirectories(i,s,this._taskService);const o=e.getSdkToolchainsDir();if(void 0!==o){const e=path_1.default.dirname(o);r=path_1.default.resolve(e,"native/build-tools/cmake/bin/ninja.exe")}const a=[];for(const e of s){const i=path_1.default.resolve(e,"CMakeCache.txt"),s=path_1.default.resolve(e,"build.ninja"),o=path_1.default.resolve(e,"rules.ninja"),n=path_1.default.resolve(e,"CMakeFiles","rules.ninja");if(fs.existsSync(i)&&fs.existsSync(s)&&(fs.existsSync(o)||fs.existsSync(n))){if(void 0!==r&&fs.existsSync(r)){const i=[];i.push(r),i.push("-C"),i.push(e),i.push("clean"),this.tryCatchExecute(i,a,e,t)}fs.existsSync(i)&&fs.unlinkSync(i)}}if(a.length>0){let e="Delete the following directories that are no longer needed:";for(const t of a)e=e.concat(os_1.default.EOL,t);this._logger.warn(e)}},this.tryCatchExecute=(e,t,r,i)=>{try{i.executeSync(e)}catch(e){t.push(r)}},this.getArchDirectories=(e,t,r)=>{for(const i of r.getProjectModel().getProductNames())for(const s of r.getTargets()){const r=path_1.default.resolve(e,i,s.getTargetName(),(0,task_util_js_1.getBuildModeName)());this.pushArchDirectories(r,t)}},this.registryAction=()=>async()=>{if(await this.terminateWorkerPool(),await this.clean(path_1.default.resolve(this._taskService.getProjectModel().getProjectDir(),"build")),this.resetRemoteHspCache(),this._taskService instanceof module_task_service_js_1.ModuleTaskService){const e=this._taskService.getModuleModel();if(!e)return;await this.clean(path_1.default.resolve(e.getProjectDir(),"build"),path_1.default.resolve(e.getProjectDir(),".test"))}},this.clean=async(e,t)=>{var r;let i=!1;i||(i=this.rmdirSyncWithBuildDir(e)),t&&(i||(i=this.rmdirSyncWithBuildDir(t)));const s=inject_util_js_1.InjectUtil.getBuildCacheParentDir(e,path_1.default.join(hvigor_1.hvigorCore.getProject().getName(),e.substring(hvigor_1.hvigorCore.getProject().getNodeDir().length)));if(s!==e&&(i||(i=this.rmdirSyncWithBuildDir(s)),(0,hvigor_common_1.isCI)())){const e=path_1.default.join(path_1.default.dirname(s),build_directory_const_js_1.BuildDirConst.CPP_OUTPUT);i||(i=this.rmdirSyncWithBuildDir(e)),i||this._logger.debug("CI scenario cleared .cxx dir.")}if(i&&this._logger._buildError(`Unable to delete ${e}. some files may be opened by another program.`)._printErrorAndExit(),"project"===this.node.classKind)return;const o=null===(r=this._taskService.getProjectModel().getProject().getPluginById(ohos_plugin_id_js_1.OhosPluginId.OHOS_APP_PLUGIN).getTaskService())||void 0===r?void 0:r.getSdkInfo();this.nativeClean(o)},this.terminateWorkerPool=async()=>{this.getWorkerPool().isActive()?(this._logger.debug("clean: Start terminating worker pool."),await this.getWorkerPool().terminate(),this._logger.debug("clean: Terminating worker pool finished."),hvigor_1.TcbStore.clear(),validator_store_js_1.ValidatorStore.clear()):this._logger.debug("clean: Worker pool is inactive.")},this.rmdirSyncWithBuildDir=e=>{let t=!1;return fs.existsSync(e)&&(t=this.rmdirSync(e,!1)),t&&this._logger._buildError(`Unable to delete ${e}. some files may be opened by another program.`)._printErrorAndExit(),t},this.rmdirSync=(e,t)=>{fs.readdirSync(e).forEach((r=>{const i=path_1.default.resolve(e,r),s=fs.lstatSync(i);if(s.isFile()||s.isSymbolicLink())try{fs.unlinkSync(i)}catch(e){hvigor_1.MetricFactory.createLogEvent(e.message,hvigor_1.MetricLogType.DEBUG),hvigor_1.MetricFactory.createLogEvent(`Cannot delete ${i}. The file may be opened by another program.`,hvigor_1.MetricLogType.WARN),this._logger.debug(e.message),this._logger.warn(`Cannot delete ${i}. The file may be opened by another program.`),t=!0}else s.isDirectory()&&(t=this.rmdirSync(i,t))}));try{let r=!0;if(!fs.existsSync(e))return t;fs.readdirSync(e).forEach((t=>{const i=path_1.default.resolve(e,t);fs.existsSync(i)&&(r=!1)})),r&&fs_extra_1.default.removeSync(e)}catch(r){hvigor_1.MetricFactory.createLogEvent(r.message,hvigor_1.MetricLogType.DEBUG),hvigor_1.MetricFactory.createLogEvent(`Unable to delete ${e}. A file may be open by another program.`,hvigor_1.MetricLogType.WARN),this._logger.debug(r.message),this._logger.warn(`Unable to delete ${e}. A file may be open by another program.`),t=!0}return t},this._taskService=t}pushArchDirectories(e,t){if(!fs.existsSync(e)||!this.isDirectory(e))return;const r=fs.readdirSync(e);for(const i of r){const r=path_1.default.join(e,i);if("arm64-v8a"===i||"armeabi-v7a"===i||"x86_64"===i||"riscv64"===i){if(!this.isDirectory(r))continue;t.push(r)}}}isDirectory(e){try{return fs.readdirSync(e),!0}catch(e){return!1}}resetRemoteHspCache(){var e;global_project_data_service_js_1.GlobalProjectDataService.getInstance().resetRemoteHspCache(),null===(e=global_project_data_service_js_1.GlobalProjectDataService.getInstance().getIntegratedHspUtils())||void 0===e||e.resetIntegratedHspCache()}}exports.Clean=Clean;
\ No newline at end of file
6.1.2 创建工程
-
在
DevEco Studio中,选择Native C++应用模板创建项目。 -
项目会自动生成关键目录
src/main/cpp/,用于存放 C/C++ 源码及编译配置:*.cpp:NAPI 模块实现代码文件。CMakeLists.txt

