一、为什么要适配 Firebird

Firebird 是一套成熟的开源关系型数据库,支持事务、存储过程、触发器、并发访问、在线备份以及嵌入式运行。与需要部署复杂服务集群的数据库不同,Firebird 的运行时相对紧凑,既可以作为独立服务端,也可以通过客户端库直接嵌入应用。这种“数据库内核 + 小型运维工具”的组合,很适合桌面软件、本地业务系统、教学实验和离线数据处理场景。

对 HarmonyOS PC 而言,数据库并不只是一个可以展示的应用窗口。开发工具、行业软件和本地生产力应用最终都需要可靠的数据存储能力。适配 Firebird,可以同时验证 HarmonyOS Native 工具链对大型 C/C++ 工程的支撑情况,以及 Qt 桌面界面、动态库、子进程、文件权限和应用沙箱能否组成一条真正可用的数据库链路。

本次适配以 Firebird 6.0 开发版本为基础,目标设备为 ARM64 HarmonyOS PC,应用 BundleName 为 org.firebirdsql.firebird.ohos,Native ABI 为 arm64-v8a。鸿蒙端采用 Stage 模型承载 Qt 5.15.12 Widgets 管理界面,并将 fbclient、Engine14、服务端和常用维护工具随签名 HAP 一并交付。最终目标不是做一个只有按钮的演示页面,而是让用户能够在真机上选择数据库、执行 SQL、启动本地服务并读取数据库头信息。

二、先确定适配路线:界面、数据库内核与工具分层

Firebird 上游工程默认运行在 Linux、macOS 和 Windows 等传统桌面或服务器环境。其构建过程会先生成本机可执行的引导工具,再利用这些工具生成消息资源、SQL 解析代码和安全数据库;运行阶段又需要动态加载数据库引擎、国际化模块,并调用多个独立维护程序。直接把上游产物复制进 HAP,既无法完成交叉编译,也会遇到应用沙箱禁止执行普通 ELF 文件的问题。

项目因此按四层拆分适配边界:

层次上游默认方式HarmonyOS PC 适配方式
构建期目标产物参与后续代码与数据库生成先完成宿主机 bootstrap,再交叉编译 ARM64 目标产物
应用入口传统桌面 main() 与窗口事件循环Stage EntryAbility + XComponent 承载 Qt QPA
数据库访问客户端动态加载引擎和插件HAP 内加载 libfbclient.solibEngine14.solibfbintl.so
原生工具通过 exec / QProcess 启动独立程序使用 NativeChildProcess 加载 ET_DYN 工具并调用其导出的 main

在这套结构中,ArkTS 只负责 Ability 生命周期与窗口宿主,Qt Widgets 负责连接信息、SQL 编辑、维护工具选择和日志展示,Firebird 原生代码继续负责数据库事务、服务和维护语义。适配层没有重新实现数据库逻辑,也没有用静态文本伪装命令执行结果。

三、项目结构与交付内容

仓库保留 Firebird 上游目录,并把 HarmonyOS 工程集中放在 ohos/ 下:

ohos_firebird/
├── src/                                  # Firebird 核心、客户端与维护工具源码
├── builds/                               # 上游构建配置和安装资源
├── CMakeLists.txt                        # Firebird CMake 构建入口及 OHOS 条件配置
├── README.OpenHarmony_CN.md              # 当前适配能力与边界说明
└── ohos/
    ├── AppScope/                         # 应用名称、图标和 Bundle 配置
    ├── native/
    │   ├── build-core.sh                 # Host + OHOS 两阶段构建
    │   └── ohos-toolchain.cmake          # DevEco Native 工具链入口
    ├── runtime/firebird/                 # 汇总后的 ARM64 Firebird 运行时
    ├── entry/src/main/ets/               # Stage 与 XComponent 宿主
    ├── entry/src/main/cpp/
    │   ├── firebird_ohos_shell.cpp       # Qt 管理端、嵌入式 SQL 和子进程桥接
    │   └── CMakeLists.txt                # Qt、QPA、child_process 链接配置
    ├── qtforharmony_sdk/                 # 项目内 Qt for HarmonyOS SDK
    └── build-hap.sh                      # 运行时检查、同步与 HAP 构建

打包后的运行时不只包含客户端库,还包括服务端和常用运维命令:

runtime/firebird/
├── bin/firebird
├── bin/isql
├── bin/gstat
├── bin/gfix
├── bin/gbak
├── bin/gsec
├── bin/nbackup
├── bin/fbtracemgr
├── bin/fbsvcmgr
├── lib/libfbclient.so
├── plugins/libEngine14.so
├── intl/libfbintl.so
├── firebird.msg
└── security6.fdb

代码与数据采用不同的落点:签名 HAP 的代码目录保存 ELF、共享库和插件,/data/storage/el2/base/files/firebird 保存数据库、临时文件、锁文件和可写配置。这样既符合 HarmonyOS 的代码完整性约束,也避免数据库写入只读安装目录。

四、在 HarmonyOS PC 真机上完成核心验证

以下五张截图来自本次构建的签名 HAP 在 HUAWEI MateBook Pro(型号 HAD-W32)真机上的实际运行画面,设备分辨率为 3120×2080,处理器 ABI 为 arm64-v8a。测试通过 HDC 安装并启动 org.firebirdsql.firebird.ohos,随后在应用中完成路径配置、版本读取、SQL 查询、服务子进程启动和 gstat 数据库检查;画面中的路径、版本号、进程号和数据库头数据均来自真机运行结果。

1. 配置 Firebird 运行目录与本地数据库

应用主窗口将 Firebird 根目录、数据库文件、用户和密码集中在顶部,下面提供 SQL 控制台、数据库维护和运行日志三个工作页。本次测试使用应用可写目录中的 security6.fdb,数据库文件路径为 /data/storage/el2/base/files/firebird/security6.fdb

在这里插入图片描述

窗口并不是与 Native 运行时脱节的说明页。顶部连接参数会被 SQL 执行、服务启动和维护工具共同使用;密码输入采用掩码显示,维护工具参数则按 Firebird 原生命令行规则传递,不经过 shell 拼接。

2. 从真机加载客户端库并读取版本

点击“检查版本”后,管理端从签名 HAP 的 Firebird 运行时中加载 libfbclient.so,调用客户端版本接口。真机返回 LI-T6.3.0.2120 Firebird 6.0 Initial,说明当前页面实际接通了目标端 ARM64 客户端库。

在这里插入图片描述

版本检查同时验证了 HAP 内 Native 库的路径与动态链接关系。若客户端库没有随包同步、依赖缺失或不符合目标 ABI,调用会在加载阶段失败,不会得到图中的版本结果。

3. 使用嵌入式 C API 执行真实 SQL

SQL 控制台执行:

select 'Firebird Qt' as CLIENT from RDB$DATABASE;

管理端通过 libfbclient 完成数据库 attach、事务开启、SQL prepare/execute、结果描述、逐行 fetch、提交和 detach。真机日志返回列名以及 Firebird Qt 数据行,证明数据库引擎、客户端库、Engine14 插件、凭据和本地数据库文件已经形成完整闭环。

在这里插入图片描述

这里没有把 SQL 交给页面脚本模拟。执行过程沿用 Firebird C API,错误信息也通过 isc_interprete 转换为可读文本,因此后续接入 DDL、DML 或业务查询时仍使用同一套数据库语义。

4. 通过 NativeChildProcess 启动 Firebird 服务入口

传统桌面版可以用 QProcess 直接执行 firebird,但 HarmonyOS 应用沙箱不允许对 HAP 代码目录中的普通 ELF 直接调用 exec。适配后,Qt 管理端请求 NativeChildProcess 创建原生子进程,由子进程加载 Firebird ET_DYN 模块并调用导出的 main。截图中服务入口已经返回真实子进程 pid 26667

在这里插入图片描述

这一步验证的是 HarmonyOS 原生进程桥接和 Firebird 服务入口已经接通。当前应用形态仍属于前台管理端内启动的本地服务,不把它描述为系统级常驻守护进程;后台托管、多实例与异常拉起需要后续结合系统服务策略继续完善。

5. 运行 gstat 读取数据库头信息

最后从“数据库维护”页选择 gstat,传入 -h 和真机数据库路径。输出显示数据库页大小为 8192、ODS 版本为 14.0、数据库方言为 3,并给出事务序号、数据库 GUID、创建时间和 force write 属性。

在这里插入图片描述

命令路径位于 HAP 的 ARM64 代码目录,输出通过子进程管道回传到 Qt 日志。截图中的 Implementation 字段记录了该数据库文件由宿主机构建阶段创建时的实现信息;它描述数据库文件的创建来源,不代表当前 gstat 在 macOS 上运行。当前命令和界面都运行在已连接的 ARM64 HarmonyOS PC 真机上。

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

难点一:Firebird 不是一次交叉编译就能结束的工程

Firebird 构建依赖 boot_gpreboot_isqlbuild_msg 等本机工具,这些工具必须先在构建主机上运行,生成目标编译所需的源码、消息文件和数据库资源。如果直接把 CMake 指向 OHOS 工具链,本机无法执行 ARM64 目标程序,构建会停在 bootstrap 阶段。

ohos/native/build-core.sh 因此把流程分为 Host 与 Cross 两段。Host 阶段生成引导工具、firebird.msg 和带完整安全表结构的 security6.fdb,并在打包前验证 PLG$LEGACY_SEC.PLG$USERS 等关键对象确实存在;Cross 阶段通过 NATIVE_BUILD_DIR 复用这些宿主机产物,再生成 ARM64 的 fbclient、Engine14、服务端和维护工具。数据库文件不是随便复制的空文件,而是构建链的一部分。

难点二:应用沙箱拒绝传统 exec 调用

最初沿用 QProcess 启动 gstatgbakfirebird 时,真机返回 execvp: Permission denied。问题不在可执行位,也不是重新签名就能解决,而是 HarmonyOS 对应用代码执行来源有明确限制:HAP 内代码必须按平台允许的方式加载,不能像普通 Linux 目录一样任意执行。

当前实现使用 QOhChildProcess 创建原生子进程,子进程再 dlopen 已签名代码目录中的 ET_DYN 工具并解析 main。父进程保留 stdout/stderr 管道和退出状态监听,因此 Qt 页面仍能得到原生命令的真实输出。为了让工具能够被加载,OHOS 目标链接还保留了动态符号表中的 main

难点三:只读代码目录与可写数据库目录必须彻底分开

Firebird 通常会从安装根目录寻找配置、消息文件、插件和安全数据库,同时还要创建锁文件、临时文件和普通数据库。HarmonyOS 中,签名代码目录适合加载原生模块,却不适合承载运行时写入;应用数据目录可写,却不能被当作任意原生代码目录执行。

适配层在启动时分别设置 FIREBIRDFIREBIRD_MSGFIREBIRD_TMPFIREBIRD_LOCKFIREBIRD_OHOS_ROOT。代码、Engine14 与国际化插件留在 HAP,数据库和运行状态落到应用沙箱。路径职责明确后,升级 HAP 不会把数据库写进只读目录,维护工具也能与 SQL 控制台使用同一个数据根。

难点四:动态链接命名空间与插件发现方式不同

Firebird 的客户端会在运行时发现并加载数据库引擎与国际化模块。普通桌面系统允许按配置中的绝对路径 dlopen,HarmonyOS 的动态链接命名空间则会限制应用随意跨目录加载。仅仅把 libEngine14.so 放进包内,客户端仍可能报告找不到 provider。

管理端在执行嵌入式 SQL 前,先通过 Qt 的库加载接口显式加载 Engine14 和 libfbintl.so,让 Firebird 后续复用已经进入进程的模块句柄。Native 运行时同时使用相对 RUNPATH,并随包提供 libc++_shared.so,避免目标程序依赖开发机上的构建绝对路径。

难点五:ICU 在宿主机和 OHOS 上不是同一套接口形态

Host 阶段使用 macOS ICU 生成安全数据库,Cross 阶段则必须使用 OpenHarmony sysroot 中的头文件和系统 ICU。两套环境如果混用,轻则在链接阶段出现符号版本不一致,重则产物能够生成却在真机动态加载时失败。

构建脚本把 HOST_ICU_INCLUDE_DIRHOST_ICU_LIB_DIROHOS_ICU_INCLUDE_DIR 分开管理。针对 OpenHarmony 提供单一未版本化 libicu.so 的情况,源码对 ICU 加载名和部分安全回调做了 OHOS 分支处理,确保字符集转换接口在目标系统上能够解析。

难点六:Qt 窗口必须服从 Stage 生命周期

Qt Widgets 原本由 main() 创建应用并进入事件循环,HarmonyOS 则由 EntryAbility 管理窗口创建、前后台和销毁。工程通过 ArkTS 创建 XComponent,Qt for HarmonyOS QPA 将 Widgets 窗口挂载到系统 Surface,再由 libentry.so 初始化管理端。

真机上的空白窗口问题往往不能只看 Qt 日志,需要同时检查 Ability、XComponent、QPA 插件和 Native 入口。当前应用图标、标题栏、最大化窗口、输入控件和三个工作页均已在真机验证,说明这几层生命周期已经正确衔接。

六、构建、安装与真机运行

工程当前使用 HarmonyOS SDK 6.0.2(22),目标 ABI 为 arm64-v8a。Qt 环境搭建完成后,先生成 Firebird Native 运行时:

cd ohos_firebird

OHOS_SDK_NATIVE=/Applications/DevEco-Studio.app/Contents/sdk/default/openharmony/native \
OHOS_BUILD_JOBS=4 \
./ohos/native/build-core.sh

脚本完成后,应在 ohos/runtime/firebird/ 中看到 firebirdisqllibfbclient.solibEngine14.solibfbintl.sofirebird.msgsecurity6.fdb。随后配置本机调试签名并构建 HAP:

OHOS_BASE_SDK_HOME=/Applications/DevEco-Studio.app/Contents/sdk \
HVIGORW=/Applications/DevEco-Studio.app/Contents/tools/hvigor/bin/hvigorw \
./ohos/build-hap.sh

签名产物位于:

ohos/entry/build/default/outputs/default/entry-default-signed.hap

连接 HarmonyOS PC 真机后安装并启动:

HDC=/Applications/DevEco-Studio.app/Contents/sdk/default/openharmony/toolchains/hdc

"$HDC" list targets
"$HDC" install -r ohos/entry/build/default/outputs/default/entry-default-signed.hap
"$HDC" shell aa force-stop org.firebirdsql.firebird.ohos
"$HDC" shell aa start -a EntryAbility -b org.firebirdsql.firebird.ohos

签名文件、证书、profile 和口令属于开发者本机配置,不应提交到公共仓库。数据库也应放在应用可写目录中,避免把运行数据与 HAP 安装代码混在一起。

七、当前能力与明确边界

当前版本已经在 ARM64 HarmonyOS PC 真机上覆盖以下能力:

  • 签名 HAP 的构建、安装、启动和 Qt Widgets 窗口显示;
  • Firebird ARM64 客户端库、Engine14 与国际化插件加载;
  • 本地 .fdb 数据库路径、SYSDBA 用户和密码输入;
  • 嵌入式 SQL 的 attach、事务、执行、结果读取与提交;
  • Firebird 客户端版本读取;
  • 通过 NativeChildProcess 启动 Firebird 服务入口和维护工具;
  • gstat -h 读取数据库头信息;
  • gfix 校验、gbak 备份以及 gsecnbackupfbtracemgrfbsvcmgr 原生命令入口;
  • 工具标准输出、错误输出和退出状态回传到统一日志页。

适配范围也需要保持清楚。当前版本以本地数据库和前台管理为主,没有把远程数据库连接、多实例、系统级后台常驻、异常自动拉起、完整备份恢复矩阵、增量恢复和长时间 Trace 会话描述为已完成。维护功能仍采用原生命令参数输入,没有提供一键式备份恢复向导或可视化用户管理页面。

因此,这一版本适合本地数据库开发、功能验证和原生维护实验,也为后续桌面数据库工具提供了可复用底座;若进入生产场景,还需要继续补充远程认证、服务托管、容灾、压力、磁盘异常和长期稳定性测试。

八、总结

Firebird 的鸿蒙 PC 适配表明,大型 Native 数据库工程的关键不在“能否生成一个 aarch64 文件”,而在于构建期工具、目标端动态库、应用沙箱、可写数据目录和桌面交互能否形成连续闭环。两阶段 bootstrap 解决了交叉编译依赖,代码与数据分区解决了运行路径问题,NativeChildProcess 则跨过了传统 exec 与 HarmonyOS 应用安全模型之间的边界。

真机上的客户端版本、嵌入式 SQL 返回值、服务子进程 pid 和 gstat 数据库头信息,说明当前版本已经具备可验证的 Firebird 原生能力,而不是只完成了 HAP 外壳。后续工作可以在这条稳定主线之上继续扩展远程访问、可视化管理、服务托管和完整备份恢复,让 Firebird 在 HarmonyOS PC 上从开发实验版本逐步走向长期可维护的数据库组件。

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

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

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

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

Logo

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

更多推荐