RStudio 鸿蒙 PC 适配全记录:以 Qt 原生工作区承载嵌入式 R
欢迎加入开源鸿蒙 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 构建,后台还有 rsession、rserver、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 + Chromium | Qt Widgets 原生工作区 |
| R 执行 | rsession 管理 R | 当前使用进程内 Embedded R |
| Web 工作台 | Electron BrowserWindow | ArkUI Web 预留外部 session 入口 |
| 文件与资源 | 桌面安装目录 | HAP rawfile 解包到应用沙箱 |
| 平台渲染 | Chromium / 系统窗口 | Qt for OpenHarmony QPA + XComponent |
这里的取舍是有意为之。当前交付重点是让 R 计算、对象、数据、绘图和帮助查询在真机上产生真实结果,而不是先复制一套外观相似但没有 R 后端的页面。等目标 ABI 的完整 rsession、rserver 和 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,产品的 targetSdkVersion 和 compatibleSdkVersion 都是 6.0.1(21),设备类型声明为 2in1 与 tablet。应用包名为 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 端生成 x、y 数据,Qt 端读取点集并完成 Native 绘制。这样保留了“R 负责数据,Plots 面板负责可视化”的工作流,同时避免把未准备好的图形依赖硬塞进 HAP。
截图中的曲线由 R 计算 x <- 1:20、y <- 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 文本浏览器显示。这个过程要求 utils、tools、帮助索引和对应资源都已正确打包;只做一个搜索框而没有这些运行时内容,真机上不会得到任何正文。
下面的截图是在真机中搜索 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.so、lib/R、etc 和 share。若 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
当前交付使用不包含 rsession 的 r-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/shTerminal 命令回显;- Native Git index 状态读取,可识别 clean、修改和未跟踪状态。
当前没有把以下能力描述为已经完成:
- 随 HAP 交付的本地
rsession与rserver; - 可离线启动的完整 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 工作台。
更多推荐




所有评论(0)