开源项目krita-ohos鸿蒙PC适配全记录
一、写在前面
欢迎加入鸿蒙PC开发者社区,共同打造开发者工具生态:鸿蒙PC开发者社区:https://harmonypc.csdn.net/
项目开源地址:https://atomgit.com/OpenHarmonyPCDeveloper/ohos_krita
欢迎在PC社区平台申请新建项目:https://atomgit.com/OpenHarmonyPCDeveloper
环境搭建文章:https://blog.csdn.net/weixin_52908342/article/details/161343743
这篇文章记录的是 Krita 在 OpenHarmony / HarmonyOS PC 上的适配过程。
和我之前那些 Electron 项目的鸿蒙适配不一样,Krita 这次走的是一条「硬核」路线。Krita 不是 Web 应用,也不能套个浏览器壳就跑起来——它是一个完整的、桌面级的数字绘画软件,底层是 C++ + Qt + 一整套 KDE Frameworks,还依赖几十个原生库(图像编解码、色彩管理、文字排版、线性代数……)。
所以这次没有捷径:要把 Krita 真正的 C++ 代码,连同它的全部原生依赖,交叉编译成 OHOS arm64,再链接成一个 libentry.so 跑在鸿蒙上。
一句话概括路线:ArkTS 起一个
XComponent→ Qt 的 OpenHarmony QPA 插件dlopen("libentry.so")→ 调用导出的qtmain→ 进入 Krita 真实的main()。
整个过程从「依赖一个都编不出来」一路调到「真机上能新建画布、能落笔、能存 .kra」。下面从架构、依赖交叉编译、Krita 本体编译、设备启动调试几个角度,把这次适配完整复盘一遍。

二、项目背景
Krita 仓库根目录的版本是:
5.4.0-prealpha (Qt5)
它的体量和一个 Web 工具完全不是一个量级:
libs/:几十个核心库(kritaimage、kritaui、kritaflake、kritapigment、kritaresources …)plugins/:上百个插件(画笔引擎、滤镜、工具、停靠面板、导入导出)- 强依赖 KDE Frameworks (KF5):KConfig / KCoreAddons / KI18n / KWidgetsAddons …
- 强依赖一大堆原生库:boost、eigen3、lcms2、exiv2、quazip、freetype、harfbuzz、fribidi、libunibreak、xsimd、immer/zug/lager …
这种项目的鸿蒙适配,特点是:
- 不能用 Web 套壳,必须真交叉编译 C++。
- 依赖是层层嵌套的:Krita 依赖 KF5,KF5 依赖 Qt,大家又都依赖一堆原生库。
- 从 macOS 交叉编译到 OHOS,工具链、平台假设、文件系统行为处处是坑。
适配方法上,我借鉴了 tupitube.desk 鸿蒙移植的「壳」思路——也就是上面那条 ArkTS → XComponent → QPA → libentry.so → qtmain 的管线,以及「项目自带一份 Qt for HarmonyOS SDK」的做法。但 Krita 本体的依赖交叉编译、源码适配、运行期方案,全部是为 Krita 重新做的。
一个从一开始就立的原则:Qt 的 SDK 一定要用项目自己的(
harmony_pc/qtforharmony_sdk/),绝不引用别的项目的 SDK。
三、总体架构
适配后的工程结构(新增 harmony_pc/):
harmony_pc/
├── AppScope/ 鸿蒙应用标识(org.kde.krita / Krita / KDE 图标)
├── entry/
│ ├── src/main/ets/ ArkTS:UIAbility + AbilityStage + XComponent 页面
│ ├── src/main/cpp/ native 入口(CMakeLists)
│ ├── libs/arm64-v8a/ 预编译原生载荷(libentry.so + 所有 .so + QPA 插件)
│ └── src/main/resources/rawfile/ Krita 运行期数据(icons/brushes/profiles…)
├── qtforharmony_sdk/ 项目自带的 Qt 5.15 for HarmonyOS SDK
└── deps/build-deps.sh Krita 专属 OHOS 依赖交叉编译框架
运行期管线和标准的「Qt for HarmonyOS」形态一致:
ArkTS UIAbility (EntryAbility.ets)
└─ 全窗口 XComponent (Index.ets)
└─ Qt OpenHarmony QPA 插件 (libplugins_platforms_qopenharmony.so)
└─ dlopen("libentry.so") → 调用导出的 qtmain()
└─ Krita 真实 main()(krita/main.cc,Q_OS_OPENHARMONY 守卫)
└─ KisApplication / KisMainWindow + 30 个库 + ~150 插件
libentry.so 本身就是 Krita:在 krita/CMakeLists.txt 里,当目标系统是 OHOS 时把 krita 目标编成名为 entry 的共享库;krita/main.cc 里导出 extern "C" qtmain() 别名,指向 Krita 的 main()。
四、依赖交叉编译框架
这是整个适配最硬的部分。我写了一个 Krita 专属的依赖交叉编译系统 harmony_pc/deps/build-deps.sh,把 Krita 的全部原生依赖按依赖顺序交叉编译成 OHOS arm64,装进项目本地的 deps/prefix/(和「自带 Qt SDK」一个原则)。
它分三层:
- tier1 基础 I/O 库:libpng、libjpeg-turbo、libtiff、giflib、libexpat、lcms2
- tier2 高层依赖:boost、eigen3、exiv2、quazip、freetype、fontconfig、harfbuzz、fribidi、libunibreak、xsimd、immer/zug/lager
- tier3 KDE Frameworks:ECM + KConfig/KCoreAddons/KGuiAddons/KWidgetsAddons/KItemViews/KI18n/KCompletion
框架本身解决了几个关键工程问题:
- 三种构建方式:CMake(多数库)、Meson(fontconfig/fribidi——因为 macOS 自带的旧
diff/awk会让它们的 autotoolsconfig.status出错)、直接编译源文件(giflib、libunibreak 这种小 C 库)。 - host 工具 bootstrap:交叉编译 KDE Frameworks 时,构建过程要在 macOS 上运行代码生成工具(
kconfig_compiler_kf5、desktoptojson)。所以用 Homebrew 的 host Qt5 先编出 host 版工具,再在交叉编译 target KF 时指过去。 - 多镜像下载 + 自动校验架构:每个产物都用
llvm-readelf验证是AArch64才算过。
每一层全绿、产物全是 AArch64 之后,才有资格去碰 Krita 本体。

五、编译 Krita 本体
依赖齐了之后,让 Krita 自己的 CMake 去 configure + 编译。这一步又给 Krita 的根 CMakeLists.txt、krita/CMakeLists.txt 以及若干源码打了 OHOS 移植补丁(全部带平台守卫,不影响桌面/安卓/Windows 构建):
- 根
CMakeLists.txt:交叉编译到 OHOS 时跳过 Objective-C / X11 / D-Bus(这些是 macOS/桌面 Linux 才有的)。 krita/CMakeLists.txt:OHOS 上把入口编成libentry.so。krita/main.cc:qtmain入口 + 运行期字体/插件/资源路径初始化。libs/resources/KoResourcePaths.cpp:OHOS 的安装前缀。libs/flake/resources/KoFontFamily.cpp:OHOS 上跳过启动期的字体缩略图渲染。libs/global/KisBezierUtils.cpp、tool_transform2/*gsl_helpers.cpp:补上 GSL 守卫 / 缺失的 include。
最终编译结果:libentry.so(导出 qtmain)+ 30 个 Krita 库 + ~150 个插件,全部是 OHOS arm64。整个 Krita 数字绘画软件,真正编出来了。

六、问题困难解决
Krita 本体编出来只是上半场。把 HAP 装到真机上点开,是连环踩坑的下半场。这部分是整个适配最有价值的经验。
6.1 困难一:libc++_shared.so 缺失,QPA 插件加载失败
第一次点开直接闪退,报 Cannot read property attachAbilityStage of undefined。往下看 hilog 才发现真正原因:
failed to load libc++_shared.so (needed by libplugins_platforms_qopenharmony.so)
所有 C++ 的 .so(QPA 插件、Qt、KF、Krita)都依赖 OHOS 的 C++ 运行时 libc++_shared.so,而它没被打进 HAP。打进去即可。
6.2 困难二:RPATH 记成了构建时的绝对路径
接着报 libunibreak.so No such file,路径居然是我 Mac 上的构建绝对路径。根因是手编的小库没设 SONAME,链接方就把绝对路径记进了 NEEDED。给 libgif/libintl/libunibreak 加上 -Wl,-soname 重编即可。
紧接着又遇到 lb_prop_bmp: symbol not found——这是我编 libunibreak 时把它的 linebreakdata.c(定义该符号的源文件)误当成「数据文件」排除了。按官方 SOURCES 精确编译解决。
6.3 困难三:沙箱里没有字体,fontconfig 直接崩
过了加载关,Krita 跑到资源注册阶段 SIGSEGV,栈在 KoFontRegistry::facesForCSSValues。原因是 HAP 沙箱里没有 /etc/fonts 配置,fontconfig 找到 0 个字体,返回空指针。
解决:在 main.cc 启动早期写一份 fontconfig 配置,指向设备自带的 /system/fonts(设备上有 257 个字体),并把 HOME/XDG/缓存都设到沙箱可写目录。
6.4 困难四:rawfile 不落盘——OHOS 不把 HAP 资源解压到磁盘
字体好了之后又崩,这次是 Krita 找不到画笔资源包。诊断发现:OHOS 根本不把 HAP 的 rawfile 解压到文件系统,它只能通过资源管理器 API 读取;而 Krita 用的是文件系统路径,于是几个候选路径全是 exists=false。
解决:在 EntryAbility.ets 里,首次启动时用 resourceManager 递归把 rawfile/share 解包到沙箱可写目录,再让 Krita 的 KRITA_INSTALL_PREFIX 指过去。
6.5 困难五:QuaZip 被系统 zlib「符号抢占」
数据有了,Krita 开始加载 .bundle 画笔包,又 SIGSEGV,栈在 QuaZip 的 I/O 回调里。根因很隐蔽:OHOS 的系统 zlib(libshared_libz.z.so)罕见地导出了 minizip 符号(unzGoToFirstFile 等),运行时把 QuaZip 自带 minizip 的内部调用「符号插入(interposition)」到了系统版本,两者 ioapi ABI 不一致,回调拿到坏指针就崩。
解决:给 QuaZip 链接加 -Wl,-Bsymbolic,让它的内部调用绑定自己的符号,不被系统库抢占。
6.6 困难六:插件路径
Krita 通过插件目录加载它的色彩引擎等插件(找不到 LittleCMS 会直接退出)。把 KRITA_PLUGIN_PATH 指向 HAP 的扁平 native lib 目录(和安卓的布局一致)即可。
把这六个坎一个个填平,Krita 就从「点开闪退」走到了「完整工作区起来、能画、能存」。
七、构建与运行
交叉编译依赖 + Krita(一次性,需要 OHOS 命令行工具 + Homebrew 的 qt@5/meson/gawk):
cd harmony_pc/deps
./build-deps.sh tier1 # 基础 I/O 库
./build-deps.sh tier2 # 高层依赖 + 文字栈
./build-deps.sh tier3 # ECM + host 工具 + KDE Frameworks
./build-deps.sh krita # configure + 编译 + 安装 Krita 本体
./build-deps.sh package # 把 libentry.so + 所有 .so + 数据 装进 HAP
构建 HAP:
cd harmony_pc
export DEVECO_SDK_HOME=<command-line-tools>/sdk
<command-line-tools>/bin/ohpm install
<command-line-tools>/bin/hvigorw --mode module -p module=entry@default \
-p product=default assembleHap --no-daemon
签名产物输出在:
harmony_pc/entry/build/default/outputs/default/entry-default-signed.hap
build-profile.json5 走的是预编译打包(不让 hvigor 重新编译 native),因为 Krita 本体由它自己的 CMake 体系构建,不适合塞进 hvigor 的单 CMakeLists。

八、真机验证
把签名 HAP 装到鸿蒙设备并启动:
HDC=<command-line-tools>/sdk/default/openharmony/toolchains/hdc
"$HDC" install -r harmony_pc/entry/build/default/outputs/default/entry-default-signed.hap
"$HDC" shell "aa start -a EntryAbility -b org.kde.krita"
实测在 HUAWEI MateBook Pro(HarmonyOS 6.0.0) 上,完整创作流程跑通:
- 启动 → 出现 Krita 欢迎页(New Image / Open Image / Recent Images / 社区链接)。
- New Image → 弹出新建文档对话框,色彩配置(sRGB-elle…icc)正常加载。
- Create → 进入完整绘画工作区:画布、工具箱、笔刷预设(缩略图已加载)、图层、颜色选择器。
- 在画布上拖拽 → 画出笔触;标题出现
*表示已修改。 - 保存 → 沙箱里生成
.kra工程文件。
全程无崩溃。一个完整的桌面级数字绘画软件,真正原生跑在了鸿蒙 PC 上。

九、适配成果
krita-ohos 已经完成:
- Krita 全部原生依赖交叉编译到 OHOS arm64(图像/IO 库 + 文字栈 + boost/eigen/exiv2/quazip + KDE Frameworks ×7 + immer/zug/lager + xsimd)
- Krita 本体交叉编译:
libentry.so(导出qtmain)+ 30 个库 + ~150 个插件,全 OHOS arm64 - ArkTS → XComponent → QPA → libentry → qtmain → Krita main 全链路打通
- 运行期方案:rawfile 沙箱解包、fontconfig 指向系统字体、插件路径、libc++_shared 打包、QuaZip 符号绑定
- 真机验证:启动 → 新建 → 绘画 → 保存 全流程跑通
十、结语
krita-ohos 这次适配,本质上是一次桌面级原生 C++/Qt 应用的鸿蒙交叉编译实战。
它和 Web 套壳完全不同——没有捷径可走,从工具链三元组、依赖层层交叉编译、KDE Frameworks 的 host 工具 bootstrap,到设备上 libc++_shared、RPATH、字体、rawfile 落盘、QuaZip 符号抢占的连环调试,每一步都得啃下来。
但结果是实打实的:一个有完整画笔引擎、图层、色彩管理、文字排版能力的专业绘画软件,真正原生运行在了鸿蒙 PC 上,能新建、能画、能存。对「鸿蒙能不能承载重型桌面原生应用」这个问题,这是一个肯定的回答。
更多推荐

所有评论(0)