華為官方適配的 KMP/CMP HarmonyOS 適配版本終於出來了,這個版本真的拖了好久了,雖然之前也有騰訊維護的 ovCompose 和 Kuikly 版本,但是現在華為官方的社群版本終於出來,也算是給了 KMP/CMP HarmonyOS 官方適配的名分。
當然,它實際上和
ovCompose和Kuikly版本也是密不可分。
事實上 KMP/CMP 適配 HarmonyOS 的門檻還是相當高的,它需要把 HarmonyOS 當作 Kotlin/Native 的新 Target 來實作,這次的實作路線需要大量的 KN 和 LLVM 適配,然後 Kotlin 會直接編譯成 HarmonyOS ELF 二進位,再用 NAPI / CAPI 和 ArkTS / ArkUI 協作完成渲染。
Kotlin/Native 用
KonanTarget描述「我要為誰輸出二進位」,每個 Target 一般有三要素:family、architecture、triple。
當然,這套 Kotlin/Native 核心實作來自騰訊 KuiklyBase 體系,CMP UI 那邊的統一渲染也是來自騰訊 ovCompose,所以專案裡你可以看到不少 // region Tencent Cod 這樣的程式碼,grep "// region Tencent Code" -r 就能列出對應修改。
KMP 適配 HarmonyOS,首先就是需要在 KonanTarget.kt 新增 OHOS 平台,同時擴充出 Family.OHOS :
OHOS_ARM64 : KonanTarget("ohos_arm64", Family.OHOS, Architecture.ARM64)OHOS_X64 : KonanTarget("ohos_x64", Family.OHOS, Architecture.X64)這兩個 Target 也意味著,從 Gradle DSL
kotlin { ohosArm64() }一直到中間 IR 的 lowering 階段,Kotlin 編譯器都知道了 HarmonyOS 平台的存在。
接著就是讓 LLVM 後端真的能產出可執行的二進位,這一步簡單說就兩件事:
Linker.kt 使用 class OhosLinker(targetProperties: OhosConfigurables) : LinkerFlags(...),並搭配 OhosConfigurables 做 dispatch那 KMP 到這裡 Kotlin 到 ELF 的工具鏈就這樣接通了,接著就是產物:
產物大致有:
libkn.so(業務通用動態庫)libkn.a(靜態庫,供 hap 二次連結)libkn_api.h(C 標頭,供宿主端 C/C++ 存取 Kotlin 匯出 API,與 libkn_api.h 配套).kexe(可執行檔)emitRuntime / emitStdlib / moduleIncludes 分別產出 runtime、stdlib、業務模組等多個 so,可按需載入、熱替換與排查符號問題

所以整個流程大概就是: Kotlin 原始碼 → Kotlin/Native 編譯器(帶 OHOS Target) → 畢昇 LLVM 19(OHOS 工具鏈) → ELF 靜態/動態庫 (.a/.so/.kexe) ,最後被 HarmonyOS 應用以 dlopen 方式載入:

完成 KMP 的基礎之後,就是 CMP 在 HarmonyOS 上的 Skia 繪製,目前也有兩條路線:
自繪製路徑和 iOS 的 KN 一致,CMP 自己持有一塊 GL Surface,自己 swap,HarmonyOS 這一側的載體是提供一個 ArkUI 的 XComponent,暴露一個原生 EGL Surface,外加觸控事件投遞:
ComposeArkUIViewController 作為入口類,接到 ArkUIViewController 的生命週期回呼後,會把 EGL 上下文與 Skia Surface 接起來ChoreographerManager 接收 HarmonyOS vsync 訊號,然後送給 ComposeSceneRender 做組合與重繪基本上都跟 ovCompose 沒什麼太大差別,一個媽生的。
這個就有意思了,透過 ArkUI RenderNode 作為掛載錨點,由 ArkUI 渲染執行緒驅動反向 draw 回呼,Compose 直接在 ArkUI 提供的 Canvas 上完成繪製,fusion 模式下 Compose 不再持有獨立 EGL/GPU 上下文,所以省去雙份 GPU 上下文與離屏 buffer 的開銷:

不過目前統一渲染的 ArkUINativeViewFusionRenderNode.kt 檔頭是:

但是實作上又是:

所以這是屬於華為的設計,還是和騰訊有關係?我也分不清楚了,但看起來還是更像是華為的實作,或者只是模板污染了?
所以看下來,目前 HarmonyOS 社群版本基本就是繼承了 KuiklyBase 和 ovCompose 的實作,算是這兩個的分支?而且目前已經合入了 JetBrains 上游 Kotlin 2.2.21 / Compose 1.9.2 ,還在加了 LTPO/DVSync 自適應幀率、CommonGC 全新演算法取代原 CMS 演算法等調整,所以也不全是騰訊的直接遷移。
不過問題來了,未來 KMP 和 CMP 在 HarmonyOS 等於是多分叉?比如:
或者後續完全分叉?開發者自己選用哪個?反正我暫時是沒搞懂。那麼如果是你,你會選哪個?