HarmonyOS鸿蒙PC开源MeldNext软件移植:开源工具Meld到鸿蒙PC实践总结
本文结合本仓库 MeldNext 的实际源码、工程结构,系统总结开源差异比较工具 Meld 从 Linux 桌面到鸿蒙 PC 的完整移植过程。
移植成功后的效果:

一、开源软件 Meld 与 MeldNext 在鸿蒙上的差异
Meld 是 GNOME 桌面环境下的可视化差异比较与合并工具(原始仓库:https://gitlab.gnome.org/GNOME/meld),而 MeldNext 是其在鸿蒙 PC 上的移植版本。两者在技术架构上存在以下核心差异:
| 维度 | 原生 Meld(Linux 桌面) | MeldNext(鸿蒙 PC) |
|---|---|---|
| UI 框架 | GTK+ 3(Python PyGObject) | ArkUI(ArkTS 声明式 UI) + XComponent 内嵌原生渲染 |
| 编程语言 | Python 为主,C 为辅 | TypeScript(ArkTS) + C++17 |
| 运行形态 | 独立桌面应用(进程直接启动) | HAP 应用包,通过 Ability 生命周期管理 |
| UI 渲染 | GTK 窗口系统 + Cairo 绘制 | ArkUI 框架 + OpenGL ES 3.x 硬件加速 |
| 差异比较引擎 | 内置 Python diff 库 + GNU diffutils | GNU diffutils 3.10/3.12 交叉编译为 HNP 二进制 |
| 文本编辑器 | GtkSourceView | Scintilla + Lexilla 通过 OpenGL 渲染到 XComponent |
| 版本控制 | 通过 subprocess 调用 git/svn | Git + SVN 通过 Lycium 交叉编译为 HNP 运行 |
| 字符编码 | Python 内置编码检测 | uchardet(Mozilla 编码检测库)通过 N-API 桥接 |
| 构建系统 | Meson + Python setuptools | Hvigor + CMake + Lycium |
| 部署方式 | apt/pip 安装 | DevEco Studio 构建签名 → hdc install HAP |
| 包名 | org.gnome.meld | com.develop.opensource.meldnext |
| 设备支持 | Linux 桌面 | phone + 2in1(鸿蒙 PC/平板) |
| 商用分发 | GPL-3.0 开源社区 | GPL-3.0,上架鸿蒙应用市场 |
核心差异在于:MeldNext 没有将 GTK+ 的 Python 代码移植到鸿蒙,而是完全使用 ArkTS 重写了 UI 层,同时将核心 C/C++ 底层库通过交叉编译的方式嵌入鸿蒙运行时,通过 N-API 和 HNP 机制与 ArkTS 交互。
二、技术架构与技术原理
2.1 总体架构
┌─────────────────────────────────────────────────────────────────────┐
│ ArkTS UI 层 (ArkUI) │
│ ┌───────────┐ ┌───────────┐ ┌───────────┐ ┌───────────────────┐ │
│ │ 文件比较 │ │ 文件夹比较 │ │ 版本控制 │ │ 设置/快捷键/历史 │ │
│ │ 页面 │ │ 页面 │ │ 页面 │ │ 页面 │ │
│ └─────┬─────┘ └─────┬─────┘ └─────┬─────┘ └─────────┬─────────┘ │
│ │ │ │ │ │
│ └─────────────┴──────┬──────┴──────────────────┘ │
│ │ │
│ ┌────────┴────────┐ │
│ │ N-API 桥接层 │ │
│ │ (napi_init.cpp) │ │
│ └────────┬────────┘ │
├─────────────────────────────┼─────────────────────────────────────┤
│ ┌────────────┴────────────┐ │
│ │ 原生 C++ 模块 │ │
│ ┌─────────────┼──────────────────────┼──────────────┐ │
│ │ entry 模块 │ seditor 模块 │ shell 模块 │ │
│ │ (libentry) │ (libxrender) │ (libshell) │ │
│ │ │ │ │ │
│ │ · diffutils │ · Scintilla 编辑器 │ · VT100 终端 │ │
│ │ · uchardet │ · Lexilla 词法分析 │ · FreeType │ │
│ │ · SHA256 │ · RTTR 反射 │ · utf8proc │ │
│ │ · 命令执行 │ · OpenGL ES 渲染 │ · EGL/GLES │ │
│ └─────────────┴──────────────────────┴──────────────┘ │
├─────────────────────────────┼─────────────────────────────────────┤
│ ┌────────┴────────┐ │
│ │ HNP 运行时 │ │
│ │ (/data/service/ │ │
│ │ hnp/) │ │
│ │ · diff / cmp │ │
│ │ · git / svn │ │
│ └─────────────────┘ │
├─────────────────────────────────────────────────────────────────────┤
│ HarmonyOS 系统层 │
│ (AbilityKit, ArkUI, HiLog, EGL/GLES, native_window, uv, ace_napi) │
└─────────────────────────────────────────────────────────────────────┘
2.2 核心技术原理
2.2.1 N-API 桥接机制
N-API(Native API)是鸿蒙系统中 ArkTS 与 C++ 原生代码交互的标准通道。MeldNext 注册了三个 N-API 模块:
| 模块名 | 动态库 | 注册函数 | 暴露能力 |
|---|---|---|---|
entry |
libentry.so |
RegisterEntryModule |
diffFile, detectCharset, syscall_sync/async/buf/by_line, calcHash, setEnv |
seditor |
libxrender.so |
RegisterSeditorModule |
ScintillaWidget 创建/释放, lexerList, createNativeNode |
shell |
libshell.so |
(通过 napi_init) | run, send, createSurface, destroySurface, resizeSurface, scroll, checkCopy/Paste |
N-API 桥接的关键模式包括:
- 同步调用:
napi_call_function直接调用 JS 回调,适用于短耗时操作(如setEnv、detectCharset) - 异步工作:
napi_create_async_work+napi_queue_async_work,适用于耗时操作(如diffFile、syscall_async) - 逐行流式回调:
napi_create_threadsafe_function+ 跨线程回调,适用于命令执行的逐行输出(如syscall_by_line)
// 异步工作模式示例
napi_create_async_work(env, nullptr, resourceName,
ExecuteDiffFileCB, // 后台线程执行
CompleteDiffFileCB, // 主线程完成回调
data, &asyncWork);
napi_queue_async_work(env, asyncWork);
// 逐行流式回调模式
napi_create_threadsafe_function(env, jsCallback, ..., CallJs, &safeFunc);
// 后台线程逐行调用
napi_call_threadsafe_function(safeFunc, lineData, napi_tsfn_blocking);
2.2.2 XComponent + OpenGL ES 原生渲染
对于 Scintilla 编辑器(seditor 模块)和终端模拟器(shell 模块),MeldNext 使用 XComponent 组件在 ArkUI 中嵌入原生渲染表面:
ArkTS XComponent 控件
│ id="xcomponent", type="surface"
│
▼
C++ Native 层
│ OH_NativeWindow_CreateNativeWindowFromSurfaceId(surfaceId)
│ eglGetDisplay() → eglInitialize() → eglCreateWindowSurface()
│ eglMakeCurrent() → OpenGL ES 渲染循环
│
▼
渲染到屏幕
│ eglSwapBuffers(egl_display, egl_surface)
- 编辑器(seditor/xrender):Scintilla 引擎在 OhWidget 的鸿蒙平台适配层中将文本行转换为 OpenGL ES 顶点/纹理数据,通过 EGL 渲染到 XComponent 表面
- 终端(shell):VT100/xterm 终端模拟器在收到数据后解析 ANSI 转义序列,通过 FreeType 栅格化字体字形,使用 OpenGL ES 绘制到屏幕
2.2.3 HNP(HarmonyOS Native Plugin)机制
对于 GNU diffutils、Git、SVN 等命令行工具,MeldNext 采用 HNP 机制部署:
- Lycium 交叉编译:在 Ubuntu 22.04 上使用 OHOS Native SDK 交叉编译为 arm64-v8a/armeabi-v7a/x86_64 二进制
- HNP 打包:使用
hnpcli pack将二进制 + 清单文件打包为.hnp文件 - HAP 集成:在
module.json5的hnpPackages字段声明 HNP 包 - 运行时调用:通过 N-API 的
syscall_by_line()调用/data/service/hnp/下的二进制,ArkTS 接收逐行回调
2.2.4 编码检测流程
ArkTS 打开文件
│ fs.openSync(uri) → fd
│ napi.detectCharset(fd)
▼
C++ (uchardet)
│ uchardet_new() → uchardet_handle_data() → uchardet_data_end()
│ uchardet_get_charset() → 返回编码名称
▼
ArkTS 收到编码
│ 如 UTF-8, GB2312, Shift_JIS 等
│ 用于 Scintilla 编辑器正确显示文本
三、底层依赖开源库介绍及移植要求
3.1 移植库一览
| 序号 | 库名称 | 版本 | 原始用途 | 在 MeldNext 中的角色 | 移植方式 | 代码复用率 |
|---|---|---|---|---|---|---|
| 1 | GNU diffutils | 3.10/3.12 | 文件差异比较 | 核心 diff 引擎 | 源码嵌入 entry + Lycium 交叉编译 HNP | 100% |
| 2 | uchardet | latest | Mozilla 字符编码检测 | 文件编码自动识别 | 源码嵌入 entry(add_subdirectory) | ~98% |
| 3 | Scintilla | latest | 源码编辑器组件 | 文本编辑 + 语法高亮 | 源码嵌入 seditor,需编写 OHOS 平台适配 | ~90% |
| 4 | Lexilla | latest | 词法分析器集合 | 编程语言语法高亮 | Scintilla 子项目,同步移植 | ~90% |
| 5 | FreeType | latest | 字体栅格化引擎 | 终端字体渲染 | 源码嵌入 shell | 100% |
| 6 | utf8proc | latest | UTF-8 字符串处理 | 终端 Unicode 支持 | 源码嵌入 shell | 100% |
| 7 | RTTR | 0.9.6 | C++ 运行时类型反射 | xrender 属性绑定 | 源码嵌入 seditor | 100% |
| 8 | Git | v2.52.0 | 分布式版本控制 | 版本控制集成 | Lycium 交叉编译为 HNP | 100% |
| 9 | Subversion | 1.14.5 | 集中式版本控制 | 版本控制集成 | Lycium 交叉编译为 HNP | 100% |
| 10 | TinyXML | latest | XML 解析 | Scintilla 配置解析 | 源码嵌入 xrender | 100% |
3.2 移植到 HarmonyOS 需要满足的要求
3.2.1 编译工具链
| 要求项 | 说明 |
|---|---|
| 编译器 | 必须使用 BiSheng(毕昇)编译器(HarmonyOS native SDK 自带),不可使用 GCC |
| C++ 标准 | 建议使用 C++17(CMAKE_CXX_STANDARD 17) |
| CMake 版本 | 3.5.0+(OHOS SDK 自带) |
| 工具链文件 | 必须指定 ohos.toolchain.cmake 路径 |
| 架构参数 | 通过 -DOHOS_ARCH 指定目标架构 |
3.2.2 代码层面的适配要求
| 要求项 | 说明 |
|---|---|
| 平台宏 | OHOS 编译环境下默认定义 OHOS 宏,可用于条件编译 |
| POSIX API | OHOS 支持大部分 POSIX API(popen、fork、execvp、pipe、chdir、setenv 等),可直接使用 |
| 文件系统 | 使用 OHOS 路径规则(/data/storage/el2/base/haps/ 等) |
| 日志输出 | 使用 HiLog(hilog/log.h),而非 printf/cout |
| 线程模型 | 使用 N-API 的线程安全函数,不要直接操作 JS 线程 |
| OpenGL ES | 使用 EGL + GLESv3,鸿蒙支持 OpenGL ES 3.2 |
| 窗口系统 | 使用 OH_NativeWindow 而非 X11/Wayland |
3.2.3 平台适配层(Scintilla 示例)
Scintilla 的移植需要实现以下平台接口(位于 seditor/src/main/cpp/scintilla/oh/):
scintilla/oh/
├── OhWidget.cpp # 鸿蒙 XComponent Widget 封装
├── OhWidget.h
├── PlatOH.cpp # 鸿蒙平台接口(Window 创建、菜单、定时器等)
├── ScintillaOh.cpp # Scintilla 鸿蒙适配主入口
├── ScintillaOh.h
└── SurfaceOhImpl.cpp # 基于 EGL/GLES 的表面绘制实现
└── SurfaceOhImpl.h
这些文件实现了 Scintilla 的 Platform.h 中所声明的全部纯虚接口,将 Scintilla 的绘制请求转换为 OpenGL ES 渲染命令。
3.2.4 HNP 打包要求
| 要求项 | 说明 |
|---|---|
| 清单文件 | hnp.json 描述二进制安装路径和符号链接 |
| 架构匹配 | HNP 包架构必须与设备架构一致 |
| 安装路径 | 安装到 /data/service/hnp/ 目录 |
| DevEco 集成 | 需要修改 packing-tool-options.js 支持 --hnp-path 参数 |
四、移植流程
4.1 总体移植流程
┌─────────────────────────────────────────────────────────────┐
│ 第1阶段:环境准备 │
│ DevEco Studio 5.0.5+ + HarmonyOS SDK + BiSheng 编译器 │
│ + OHOS Native SDK + Lycium 框架(Ubuntu 22.04) │
└─────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────┐
│ 第2阶段:底层库编译 │
│ │
│ ┌─────────────────────┐ ┌─────────────────────────────┐ │
│ │ 方式A:CMake 嵌入 │ │ 方式B:Lycium 交叉编译 │ │
│ │ │ │ │ │
│ │ · uchardet │ │ · diffutils → HNP │ │
│ │ · diffutils(部分) │ │ · git → HNP │ │
│ │ · FreeType │ │ · svn → HNP │ │
│ │ · utf8proc │ │ · svn-apr / svn-apr-util │ │
│ │ · RTTR │ │ │ │
│ │ · TinyXML │ └─────────────────────────────┘ │
│ │ · Scintilla(需适配) │ │
│ └─────────────────────┘ │
└─────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────┐
│ 第3阶段:N-API 桥接开发 │
│ │
│ 编写 napi_init.cpp 注册模块和导出函数 │
│ 编写 types/libentry/Index.d.ts 类型声明 │
│ 配置 oh-package.json5 声明原生库依赖 │
└─────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────┐
│ 第4阶段:集成到 DevEco │
│ │
│ 1. 配置 build-profile.json5(签名、产品、模块) │
│ 2. 配置 module.json5(hnpPackages、权限、Ability) │
│ 3. 放置 HNP 包到 entry/hnp/<abi>/ │
│ 4. 修改 packing-tool-options.js(支持 HNP 路径) │
│ 5. 编写 ArkTS UI 页面 │
│ 6. 编写 XComponent 控件 │
└─────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────┐
│ 第5阶段:签名 + 安装 │
│ │
│ DevEco Studio Build & Run → 自动签名 → 安装到真机 │
│ 或 hdc install entry-default-unsigned.hap │
└─────────────────────────────────────────────────────────────┘
4.2 编译指令
4.2.1 CMake 编译(自动由 Hvigor 调用)
每个模块的 build-profile.json5 中配置 externalNativeOptions,Hvigor 构建时会自动调用 CMake:
{
"externalNativeOptions": {
"path": "./src/main/cpp/CMakeLists.txt",
"arguments": "",
"cppFlags": ""
}
}
如需手动调试,可使用以下命令:
# entry 模块
cmake -B build -G Ninja \
-DCMAKE_TOOLCHAIN_FILE="$SDK_PATH/build/cmake/ohos.toolchain.cmake" \
-DOHOS_ARCH=arm64-v8a \
-DCMAKE_BUILD_TYPE=Debug
cmake --build build
关键 CMakeLists.txt:
# entry/src/main/cpp/CMakeLists.txt
cmake_minimum_required(VERSION 3.5.0)
project(ohpc-app-diffui2)
set(CMAKE_PLATFORM_NO_VERSIONED_SONAME TRUE)
add_subdirectory(uchartdet)
add_library(entry SHARED napi_init.cpp napi_cmd.cpp napi_sha256.cpp)
target_link_libraries(entry PUBLIC libace_napi.z.so hilog_ndk.z libuchardet libohcrypto.so)
# seditor/src/main/cpp/CMakeLists.txt
set(CMAKE_CXX_STANDARD 17)
add_subdirectory(scintilla) # 含 oh/ 平台适配
add_subdirectory(rttr-0.9.6)
add_subdirectory(xrender) # OpenGL 渲染层
add_library(seditor SHARED napi_init.cpp)
target_link_libraries(seditor PUBLIC libace_napi.z.so hilog_ndk.z)
# shell/src/main/cpp/CMakeLists.txt
set(CMAKE_CXX_STANDARD 17)
find_library(EGL-lib EGL)
find_library(GLES-lib GLESv3)
add_subdirectory(freetype)
add_subdirectory(utf8proc)
add_library(shell SHARED napi_init.cpp terminal.cpp)
target_link_libraries(shell PUBLIC
libace_napi.z.so ${EGL-lib} ${GLES-lib}
libnative_window.so libhilog_ndk.z.so freetype utf8proc)
4.2.2 Lycium 交叉编译(Ubuntu 22.04)
环境准备:
# 1. 安装 Ubuntu 22.04
# 2. 下载 OHOS Native SDK(如 native-linux-x64-5.0.1.111-Release.zip)
# 3. 解压到 ~/sdk/
# 4. 克隆 tpc_c_cplusplus 仓库
git clone https://gitcode.com/openharmony-sig/tpc_c_cplusplus ~/tpc_c_cplusplus
# 5. 设置环境变量
export OHOS_SDK=~/sdk
编译 diffutils:
cd ~/tpc_c_cplusplus
# 新建 ~/tpc_c_cplusplus/thirdparty/diffutils/HPKBUILD
# 编写 HPKBUILD 脚本(见 lycium/diff.HPKBUILD.sh)
./lycium/build.sh diffutils
# 输出:~/tpc_c_cplusplus/lycium/usr/diffutils/<arch>/
编译 Git:
# 新建 ~/tpc_c_cplusplus/thirdparty/git/HPKBUILD
# 依赖 zlib
./lycium/build.sh git
编译 SVN(按依赖顺序):
# 1. 先编译依赖
./lycium/build.sh svn-apr
./lycium/build.sh svn-apr-util
# 2. 再编译 SVN
./lycium/build.sh svn
打包为 HNP:
hnpcli pack -i ./arm64-v8a -o ./
HNP 清单(hnp.json):
{
"type": "hnp-config",
"name": "superred.diffui",
"version": "1.0",
"install": {
"links": [
{ "source": "/bin/diff", "target": "diff" },
{ "source": "/bin/cmp", "target": "cmp" },
{ "source": "/bin/diff3", "target": "diff3" },
{ "source": "/bin/sdiff", "target": "sdiff" },
{ "source": "/bin/mdiff", "target": "mdiff" }
]
}
}
4.3 上下层交互方式
4.3.1 N-API 直接调用(同步/异步)
// ArkTS 侧
import napi from 'libentry.so';
// 同步调用(编码检测)
const encoding: string = napi.detectCharset(fd);
// 异步带回调(差异比较)
napi.diffFile(file1Path, file2Path, (result: string) => {
// 处理 diff 结果
});
// 异步带逐行回调(命令执行)
napi.syscall_by_line("diff -u a.txt b.txt", "", (line: string) => {
// 逐行处理输出
if (line === "[EOF]") { /* 完成 */ }
});
// C++ 侧导出函数(napi_init.cpp)
static napi_value DetectCharset(napi_env env, napi_callback_info info) {
// 1. 解析参数
napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
napi_get_value_int32(env, args[0], &fd);
// 2. 调用 uchardet
auto handle = uchardet_new();
// ... 读取文件数据 ...
uchardet_handle_data(handle, buffer, len);
uchardet_data_end(handle);
const char *charset = uchardet_get_charset(handle);
// 3. 返回结果
napi_create_string_utf8(env, charset, strlen(charset), &result);
return result;
}
4.3.2 XComponent + OpenGL ES 原生渲染
// ArkTS 侧 - 编辑器
@Builder
build() {
XComponent({
id: 'editor_xcomponent',
type: 'surface',
controller: this.xcController
})
.onLoad(() => {
let surfaceId = this.xcController.getXComponentSurfaceId();
napi.createNativeNode(surfaceId); // 创建 Scintilla 编辑器
})
}
// ArkTS 侧 - 终端
@Builder
build() {
XComponent({
id: 'terminal_xcomponent',
type: 'surface',
controller: this.xcController
})
.onLoad(() => {
let surfaceId = this.xcController.getXComponentSurfaceId();
napi.createSurface(surfaceId); // 创建 EGL 表面
napi.run(); // 启动终端进程
})
}
// C++ 侧 - 终端表面创建
static napi_value CreateSurface(napi_env env, napi_callback_info info) {
// 1. 获取 surfaceId
napi_get_value_bigint_int64(env, args[0], &surface_id, &lossless);
// 2. 创建 NativeWindow
OHNativeWindow *native_window;
OH_NativeWindow_CreateNativeWindowFromSurfaceId(surface_id, &native_window);
// 3. 初始化 EGL
egl_display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
eglInitialize(egl_display, &major_version, &minor_version);
// ... 创建 EGL 上下文和表面 ...
// 4. 进入 EGL 渲染循环
eglMakeCurrent(egl_display, egl_surface, egl_surface, egl_context);
}
4.3.3 HNP 命令执行
// ArkTS 调用 HNP 二进制
napi.syscall_by_line(
"diff --text --color=never --normal file1.txt file2.txt",
"/data/service/hnp", // HNP 安装路径
(line: string) => {
// 接收 diff 输出行
process.stdout += line;
}
);
4.4 关键配置文件
| 文件 | 关键作用 |
|---|---|
build-profile.json5(根) |
签名配置(debug/release/release_test)、产品定义(targetSdk 5.1.1)、编译器(BiSheng)、模块注册 |
entry/build-profile.json5 |
externalNativeOptions 指向 CMakeLists.txt |
entry/src/main/module.json5 |
声明 hnpPackages(diffui.hnp, base.hnp, git.hnp, superred_svn.hnp)、权限、Ability |
entry/oh-package.json5 |
声明对 libentry.so 和 @app/seditor 的依赖 |
entry/src/main/cpp/types/libentry/Index.d.ts |
N-API 类型声明 |
AppScope/app.json5 |
应用元信息(bundleName, versionCode, versionName) |
tools/packing-tool-options.js |
修改后的 DevEco 打包工具,支持 HNP 路径注入 |
keys/* |
签名证书(debug.p12, release.p12, *.p7b profile) |
4.5 注意事项
- ABI 一致性:CMake 编译时的
OHOS_ARCH必须与设备架构一致。真机一般为arm64-v8a,模拟器为x86_64 - HNP 依赖顺序:SVN 的编译必须先编译
svn-apr和svn-apr-util,再编译svn - Scintilla 平台适配:Scintilla 的
oh/目录需要实现SurfaceImpl、WindowImpl等平台抽象接口,工作量约占 Scintilla 移植的 90% - OpenGL 版本:使用
GLESv3(OpenGL ES 3.2),而非桌面 OpenGL - 线程安全:
syscall_by_line的后台线程输出必须通过napi_create_threadsafe_function转发到 JS 线程,不可直接调用 JS 回调 - 权限声明:文件比较功能需要声明
READ_WRITE_DOCUMENTS_DIRECTORY、READ_WRITE_DOWNLOAD_DIRECTORY、READ_WRITE_DESKTOP_DIRECTORY、FILE_ACCESS_PERSIST权限 - 打包工具修改:标准的 DevEco 打包工具不支持 HNP,需按
tools/packing-tool-options.js修改后替换原始文件 - 字体资源:终端模块的 TTF 字体需放入
resources/rawfile/目录,C++ 侧通过 OHOS 资源 API 读取 - 签名算法:必须使用
SHA256withECDSA,不兼容 SHA1 - 开发环境限制:DevEco Studio 需安装在 D 盘且路径不含空格
五、移植总结
5.1 移植模式
MeldNext 项目展示了三种底层库移植到鸿蒙 PC 的模式:
| 模式 | 适用场景 | 代表库 | 复杂度 |
|---|---|---|---|
| 源码内嵌 + N-API | 库源码较小,需频繁调用 | diffutils, uchardet | ★★☆ |
| 源码适配 + XComponent | 需要原生渲染/复杂交互 | Scintilla, 终端 | ★★★ |
| Lycium/HNP 独立二进制 | 独立命令行工具,不常交互 | Git, SVN, diff | ★☆☆ |
5.2 关键技术决策
- UI 层全部使用 ArkTS,不保留 Qt/GTK 等传统 UI 框架,确保最佳鸿蒙原生体验与性能
- C++ 引擎层完全复用,只需编写 HarmonyOS 平台适配层(约 5-10% 的代码量)
- OpenGL ES + XComponent 作为高性能原生渲染通道,解决编辑器/终端的复杂绘制需求
- N-API 异步模型使用
napi_create_async_work+napi_create_threadsafe_function,确保不阻塞 UI 线程 - HNP 机制让传统命令行工具无需改造即可在鸿蒙上运行,大幅降低移植成本
5.3 效果
| 指标 | 说明 |
|---|---|
| 代码复用率 | C++ 核心引擎 ~95% 未修改,仅需编写 ~5% 的平台适配层 |
| 功能完整性 | 双文件/三文件比较、文件夹比较、版本控制集成、内置编辑器、终端模拟器均正常运行 |
| 架构支持 | arm64-v8a(真机)、x86_64(模拟器)、armeabi-v7a |
| 目标 SDK | HarmonyOS 5.1.1(兼容 5.0.3),支持 phone 和 2in1(PC/平板) |
5.4 关键技术决策
- UI 层 100% ArkTS 重写:不保留 GTK+ 代码,充分利用鸿蒙 ArkUI 声明式框架和布局能力
- C++ 引擎层跨平台复用:GNU diffutils、Scintilla、FreeType、uchardet 等库的算法核心完全不变,仅在平台接口层做鸿蒙适配
- OpenGL ES + XComponent 承载原生渲染:解决编辑器/终端的高性能绘制需求(60fps 滚动、即时渲染)
- HNP 承载命令行工具:无需改写 Git/SVN/diffutils 的源码,通过 Lycium 一键交叉编译即完成移植
- N-API 异步 + 线程安全回调:保证 UI 线程不阻塞,命令输出可以逐行流式渲染到界面
5.6 参考资源
- 原始 Meld 仓库:https://gitlab.gnome.org/GNOME/meld
- MeldNext 鸿蒙开源地址:https://gitcode.com/OpenHarmonyPCDeveloper/MeldNext
- OpenHarmony 三方库移植指导:https://gitcode.com/openharmony-sig/tpc_c_cplusplus
- DevEco Studio:https://developer.harmonyos.com/cn/develop/deveco-studio/
更多推荐




所有评论(0)