欢迎加入开源鸿蒙 PC 社区:https://harmonypc.csdn.net/

欢迎在 PC 社区平台申请新建项目:https://atomgit.com/OpenHarmonyPCDeveloper

适配开源地址:https://atomgit.com/OpenHarmonyPCDeveloper/ohos_rstudio

环境搭建文章:https://blog.csdn.net/weixin_52908342/article/details/161343743

一、为什么选择适配 RStudio

RStudio 是 R 语言生态中使用最广泛的集成开发环境之一。它把源代码编辑、Console、对象浏览、数据查看、绘图、帮助文档、终端和版本控制组织在同一个工作区内,既适用于统计分析和数据科学,也覆盖教学、科研与工程化开发。对 HarmonyOS PC 来说,RStudio 的价值不只是增加一款编辑器,更重要的是补齐一条从编写 R 代码到查看计算结果的本地开发链路。

这个项目也很适合作为复杂桌面应用迁移的样本。上游 RStudio 并不是单一框架程序:桌面入口使用 Electron,主工作台由 GWT 构建,后台还有 rsessionrserver、R 运行时以及大量系统组件。传统桌面环境允许这些进程和资源按安装目录协同工作,而 HAP 面临 ARM64 目标 ABI、应用沙箱、rawfile 资源提取、动态库加载和进程权限等约束。只把 Electron 窗口换成一个鸿蒙页面,无法让 R 开发流程真正运行起来。

因此,本次适配先把目标收敛为“在 HarmonyOS PC 上建立可用的核心 R 开发工作流”:应用能够安装和启动,设备端能够初始化真实 R 运行时,并把 Environment、Data Viewer、Plots、Help、Terminal 等关键结果放回桌面工作区。完整的 GWT Workbench、rsession/rserver 和 Electron 增强能力则保留清晰边界,不把尚未交付的能力包装成已经完成。

二、迁移边界:保留上游源码,新增鸿蒙运行面

适配代码集中在仓库的 ohos/ 目录,上游 src/e2e/ 和桌面构建入口没有被替换。这样做有两个好处:一是原有 Windows、macOS 和 Linux 构建仍然可以沿用上游方式;二是后续同步 RStudio 新版本时,鸿蒙工程与上游主体之间的冲突更容易控制。

鸿蒙端没有尝试直接运行 Electron,而是采用“ArkTS Stage 宿主 + Qt Widgets 原生工作区 + Embedded R”的组合:

层次上游 RStudio鸿蒙 PC 当前实现
应用生命周期Electron 主进程ArkTS EntryAbility
桌面工作区GWT + ChromiumQt Widgets 原生工作区
R 执行rsession 管理 R当前使用进程内 Embedded R
Web 工作台Electron BrowserWindowArkUI Web 预留外部 session 入口
文件与资源桌面安装目录HAP rawfile 解包到应用沙箱
平台渲染Chromium / 系统窗口Qt for OpenHarmony QPA + XComponent

这里的取舍是有意为之。当前交付重点是让 R 计算、对象、数据、绘图和帮助查询在真机上产生真实结果,而不是先复制一套外观相似但没有 R 后端的页面。等目标 ABI 的完整 rsessionrserver 和 GWT 产物具备稳定交付条件后,再沿现有 ArkUI Web 边界接入完整工作台。

三、鸿蒙端工程结构与启动链路

与适配直接相关的目录如下:

ohos_rstudio/
├── src/                                  # RStudio 上游 C++、R、GWT 与桌面代码
├── README.OpenHarmony_CN.md              # 鸿蒙适配说明和能力边界
└── ohos/
    ├── AppScope/                         # 应用名称、图标与 bundle 配置
    ├── build-profile.json5               # API、产品、签名和 HarmonyOS 配置
    ├── qtforharmony_sdk/                 # Qt for OpenHarmony 5.15.12
    ├── runtime/                          # 目标 ABI 的 R/RStudio runtime staging
    ├── scripts/
    │   ├── build-hap.sh                  # Native 与 HAP 构建入口
    │   ├── build-r-runtime.sh            # 交叉构建 AArch64 R
    │   ├── stage-rstudio-runtime.sh      # 整理待打包 runtime
    │   ├── audit-rstudio-runtime.sh      # runtime ABI 与内容审计
    │   └── audit-qt-hap.sh               # HAP、Qt 和 QPA 审计
    └── entry/src/main/
        ├── module.json5                  # EntryAbility、设备类型与权限
        ├── ets/
        │   ├── entryability/EntryAbility.ets
        │   └── pages/Index.ets           # XComponent 与 ArkUI Web 宿主
        ├── resources/rawfile/runtime/    # 随 HAP 交付的 R runtime
        └── cpp/
            ├── CMakeLists.txt
            ├── rstudio_qt_harmony.cpp    # 原生工作区与 R 功能入口
            └── rstudio_r_runtime_shim.c  # Embedded R Native shim

设备端启动过程可以概括为:

EntryAbility
    ├── 从 rawfile 提取 runtime 到应用沙箱
    ├── 创建 ArkUI 页面和 XComponent
    └── 启动 Qt for OpenHarmony QPA
            └── 加载 libentry.so
                    ├── 定位并加载 libR.so
                    ├── 初始化 Embedded R
                    ├── 创建 Source / Console 工作区
                    └── 创建 Environment / Data / Plots / Help / Terminal 等面板

工程当前面向 arm64-v8a,产品的 targetSdkVersioncompatibleSdkVersion 都是 6.0.1(21),设备类型声明为 2in1tablet。应用包名为 org.rstudio.qt.openharmony,版本为 0.1.0

四、核心适配过程

1. 先解决 Qt 窗口如何进入鸿蒙生命周期

Qt Widgets 不能脱离鸿蒙 Ability 独立启动。EntryAbility 负责窗口阶段和资源准备,ArkTS 页面创建 XComponent,随后 Qt QPA 插件在这个宿主内启动 Native 应用。这样,系统负责应用生命周期、窗口和权限,Qt 继续负责桌面控件、分栏与编辑交互。

工作区采用左右分栏:左侧是 Source 与 Console,右侧通过标签页承载 Environment、History、Data、Files、Packages、Plots、Help、Terminal 和 Git。这个布局保留了 RStudio 用户熟悉的操作节奏,同时避免为了复刻上游 GWT DOM 而引入一套暂时无法随 HAP 交付的浏览器工作台。

2. Embedded R 不能依赖可执行文件路径

HAP 中的资源并不等同于普通安装目录,应用沙箱的可写数据路径也不适合直接执行任意解包出来的 ELF。当前实现因此优先加载目标 ABI 的 libR.so,设置 R_HOME、库目录和运行时环境后,在 Qt 进程内完成 R 初始化。设备日志中 Rf_initialize_R 返回 0,基础表达式和命令队列都能得到结果。

这个方案还避开了一个常见误区:构建机上的 R 与目标设备上的 R 不是同一个运行时。打包前必须检查每一个动态库的 ELF 架构,并确保 base R 的资源、lazy-load 数据库、BLAS/LAPACK、zlib 和 Native 库都与 AArch64 目标一致。项目中的 staging 与 audit 脚本就是为这个边界服务的。

3. Environment 需要反映真实 .GlobalEnv

Environment 面板不是静态示例列表。点击 Refresh 后,应用通过 Embedded R 执行 ls(envir=.GlobalEnv),再把返回对象显示到 Qt 面板。下面的截图中可以看到真机启动流程和帮助查询产生的对象,其中 ohos_data 是后续 Data Viewer 使用的实际 data.frame

以下五张图片均来自本项目 HAP 在一台连接中的 HarmonyOS PC 真机上实际运行后的系统截图。设备为 AArch64,系统软件版本为 6.1.0.117,原始截图分辨率为 3120×2080。

在这里插入图片描述

4. Data Viewer 要从 R 对象生成表格

Data Viewer 接收对象名,先在 .GlobalEnv 中查找对象,再把向量或矩阵统一转换为 data.frame。为了让 Qt 侧能够稳定解析,R 端输出列名和最多 200 行数据,Native 侧完成 CSV 拆分和表格填充。

真机 smoke 创建了 ohos_data <- data.frame(x=1:3, y=4:6)。截图中的两列三行并非预置界面文本,而是由设备端 R 创建、读取并交给 Qt 表格显示的结果。

在这里插入图片描述

5. 没有 PNG/Cairo 时,绘图链路需要换一个落点

当前目标 R runtime 没有打包 libpng 和 Cairo 图形后端,如果仍然沿用桌面端设备驱动,Plot 面板只能得到失败信息。适配版本把计算和绘制拆开:R 端生成 xy 数据,Qt 端读取点集并完成 Native 绘制。这样保留了“R 负责数据,Plots 面板负责可视化”的工作流,同时避免把未准备好的图形依赖硬塞进 HAP。

截图中的曲线由 R 计算 x <- 1:20y <- x * x 后返回 20 个点,Qt 在真机窗口中绘制坐标轴、折线和数据点。

在这里插入图片描述

6. Terminal 要接受鸿蒙 Shell 的实际限制

传统桌面终端通常依赖 PTY、完整的用户 Shell 和 job control。HAP 内没有同样的进程环境,当前实现使用 /system/bin/sh -i,工作目录落在应用可写路径。启动时 Shell 会明确提示没有 TTY 和完整 job control,但普通命令输入、输出回显和工作目录内的文件操作可以运行。

截图中 ohos-terminal-smoke 是应用通过真实 Shell 子进程执行 printf 后的回显。保留警告信息比隐藏它更有价值,因为它准确说明了当前 Terminal 的能力边界。

在这里插入图片描述

7. Help 不是跳转网页,而是读取设备内 R 文档

Help 查询通过 utils::help() 定位主题,再使用 R 自带工具把 Rd 文档转换为文本,最后交给 Qt 文本浏览器显示。这个过程要求 utilstools、帮助索引和对应资源都已正确打包;只做一个搜索框而没有这些运行时内容,真机上不会得到任何正文。

下面的截图是在真机中搜索 mean 后返回的帮助内容,可以看到 Description、Usage、Arguments 等标准 R 文档段落。当前 Qt 字体渲染对部分 Rd 标题字符的字距处理仍有优化空间,但主题查找和正文读取链路已经跑通。

在这里插入图片描述

五、适配过程中最棘手的问题

难点一:RStudio 不是一个可整体替换外壳的 Electron 应用

Electron 只是上游桌面入口的一部分。真正的 IDE 还依赖 GWT Workbench、rsession、R 运行时、WebSocket/HTTP 通信和多种桌面桥。如果只迁移 Electron 菜单与窗口,最终只能得到一个无法执行 R 的空壳。当前版本先建立 Qt Native 工作区和 Embedded R 闭环,并把完整 session 明确留到后续阶段。

难点二:运行时资源必须先解包,再按真实路径初始化

ArkTS 的 rawfile 资源不能直接当作普通文件路径传给 R。EntryAbility 需要把 runtime 提取到应用沙箱,Native 层再从实际目录定位 libR.solib/Retcshare。若 R_HOME 指向 HAP 内的逻辑资源名,R 初始化可能成功一半,却会在加载 base 数据库或帮助索引时失败。

难点三:AArch64 动态库链条比主程序本身更容易出错

R 的启动不仅依赖 libR.so,还会继续加载压缩库、线性代数库和各包的 Native 库。构建机库、目标库和 SDK linker stub 一旦混用,问题可能直到真机加载 lazy-load 数据库时才暴露。项目专门构建目标侧 zlib,并在打包前审计 ELF 架构和 runtime manifest,避免“主库是 ARM64,但某个深层依赖仍是主机产物”的情况。

难点四:OpenHarmony 的系统命令行为与桌面 Unix 并不完全相同

R 的 utils 会探测系统命令并生成缓存,部分调用在 OpenHarmony 上会返回 Invalid argument。适配中增加了 Sys.which 兼容处理,并关闭不适合当前目标环境的 crc64 包缓存生成,才让 library(utils)installed.packages() 和帮助查询稳定工作。这类问题通常不是编译错误,而是在包初始化阶段才出现。

难点五:绘图、终端和 Git 都要承认平台边界

Plots 当前使用 R 计算数据、Qt Native 绘制;Terminal 可以执行普通命令,但没有完整 PTY job control;Git 面板实现了原生 index 状态读取,可识别 clean、修改和未跟踪文件,但提交与推送仍依赖外部 Git 流程。把这些边界写进设计,比在界面上提供不可用按钮更可维护。

难点六:完整 session 与核心工作流是两套覆盖口径

当前项目按核心 R 开发工作流计算约 80% 覆盖,指的是安装启动、Embedded R、Source、Console、Environment、Files、History、Data Viewer、Plots、Help、Terminal 和 Git 状态等主线。它不等于完整 RStudio 功能已经迁移。相对于包含 GWT、Electron、rsession/rserver、Quarto、Viewer、AI、Jobs 等能力的完整 runtime,当前验证覆盖约为 36%。

六、编译、安装与真机启动

使用 DevEco Studio 时,应直接打开仓库的 ohos/ 目录,并为 org.rstudio.qt.openharmony 配置与目标设备匹配的开发者签名。Qt for OpenHarmony SDK 已放在 ohos/qtforharmony_sdk/,默认目标为 arm64-v8a

基础 HAP 构建命令如下:

cd ohos
./scripts/build-hap.sh

如果 DevEco Studio 或 Native SDK 不在默认路径,可以显式指定:

cd ohos
OHOS_NATIVE_ROOT=/path/to/openharmony/native \
HVIGORW=/path/to/hvigorw \
./scripts/build-hap.sh

要把 R runtime 一起放入 HAP,先准备目标 ABI 的 staging 目录:

cd ohos
RSTUDIO_BUILD_ROOT=/path/to/rstudio/build \
RSTUDIO_R_ROOT=/path/to/arm64/r \
./scripts/stage-rstudio-runtime.sh

当前交付使用不包含 rsessionr-console profile,打包命令为:

RSTUDIO_PACKAGE_RUNTIME=1 ./scripts/build-hap.sh

构建产物位于:

ohos/entry/build/default/outputs/default/
├── entry-default-unsigned.hap
└── entry-default-signed.hap

安装和启动:

hdc install -r ohos/entry/build/default/outputs/default/entry-default-signed.hap
hdc shell aa start -a EntryAbility -b org.rstudio.qt.openharmony -m entry

打包前建议同时执行 HAP 和 runtime 审计:

./scripts/audit-qt-hap.sh entry/build/default/outputs/default/entry-default-signed.hap
./scripts/audit-rstudio-runtime.sh runtime/staged

换一台设备时需要重新配置匹配该设备的开发者签名,不能直接复用本机签名材料。签名文件与密码也不应提交到公开仓库。

七、当前已经覆盖的能力与明确边界

目前已经完成并有源码、构建审计或真机运行结果支撑的能力包括:

  • HarmonyOS Stage 工程、ARM64 Native 构建、Qt QPA 窗口和 HAP 安装启动;
  • Embedded R 初始化、基础表达式、命令队列和 Console 输出;
  • Source 多标签、文件打开保存、运行选区与运行文件的 Native 入口;
  • Environment、History、Files 和已安装包查询;
  • Data Viewer、R 数据驱动的 Qt Plot 预览;
  • 设备内 R Help 查询与 Rd 文本显示;
  • /system/bin/sh Terminal 命令回显;
  • Native Git index 状态读取,可识别 clean、修改和未跟踪状态。

当前没有把以下能力描述为已经完成:

  • 随 HAP 交付的本地 rsessionrserver
  • 可离线启动的完整 GWT Workbench;
  • Electron satellite 窗口、Viewer、Presentation 和 Chromium DevTools;
  • CRAN 包安装所需的网络、Shell、编译器与目标包 ABI 全链路;
  • Quarto、Shiny、Tutorial、AI/Chat、Jobs 和 Launcher;
  • 完整 PTY 终端、Git commit/push UI,以及全屏、分屏、浮窗的完整设备矩阵回归。

这些限制不会影响本文截图中已经验证的 Environment、Data Viewer、Plots、Terminal 和 Help,但决定了当前版本更准确的定位:它是面向 HarmonyOS PC 的 RStudio 核心工作区,而不是上游桌面版的全量替代品。

八、总结

RStudio 的鸿蒙 PC 适配说明,复杂开发工具的迁移不能从窗口框架开始,也不能以“应用能打开”作为终点。真正决定可用性的,是目标设备上能否找到并初始化正确的 R runtime,能否把对象、数据、绘图和帮助结果送回工作区,以及文件、Shell 和动态库链路是否符合 HAP 沙箱规则。

当前版本已经在 HarmonyOS PC 真机上打通 Qt/QPA 启动、Embedded R、Environment、Data Viewer、Native Plot、Terminal 和 Help 查询等核心链路,并通过 staging 与审计脚本把 ARM64 runtime 的交付边界固定下来。后续工作的重点将是补齐目标 ABI 的 rsession/rserver、GWT bundle 和包安装工具链,在保留现有 Native 核心能力的基础上,逐步接近完整 RStudio 工作台。

Logo

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

更多推荐