【KMP for OpenHarmony】-- Apollo-Kotlin 的鸿蒙适配
01 · Apollo-Kotlin 的鸿蒙适配
本文是「Apollo-Kotlin 鸿蒙适配」系列第一篇,讲怎么把上游库改造成能在 HarmonyOS 上编译。
阅读前提:了解 Kotlin Multiplatform 的expect/actual与 target 概念。
〇、环境与上游
0.1 环境搭建指引
本文不重复官方环境搭建步骤,按 CPF(CPF-KMP-CMP 社区)官方文档准备即可:
| 内容 | 链接 |
|---|---|
| 快速开始(15 分钟:装工具 → 配签名 → 跑第一个鸿蒙应用) | CPF 文档 · 快速开始 |
| 工具链插件安装、工程模板、运行调试 | CPF 文档 · 工具链介绍 |
工具链插件离线安装包(KMP OHOS Support-1.0.0.zip) | https://maven.eazytec-cloud.com/nexus/repository/file-storage/ohos-kmp-toolchain/1.0.0/KMP OHOS Support-1.0.0.zip |
| 工具链插件源码 / Issue | https://atomgit.com/CPF-KMP-CMP/ohos-kmp-toolchain |
| 文档总目录 | CPF 文档 · 目录 |
文档仓库的分支名带版本号(当前
main-2.2,对应 KMP2.2.21/ CMP1.9.2)。
工具链换代后分支与链接都会变,上面的链接若 404,从 CPF 组织首页 进docs仓库,切到与工具链版本匹配的分支。
0.2 环境版本(本文验证所用)
| 项 | 版本 / 路径 | 说明 |
|---|---|---|
| JDK | 17 | Android Studio 的 Gradle JDK 必须切到 17 |
| Android Studio | 2024.2.1+ | KMP 工程侧开发、Gradle Sync |
| DevEco Studio | 6.0.0+,本文验证 6.1.0.850 | 鸿蒙壳工程 harmonyApp/、签名、hvigor 打包 |
| HarmonyOS SDK | API 23(工具链要求 API 17+) | 在 DevEco 的 SDK Manager 中下载 |
| OHOS Kotlin 工具链 | 2.2.21-1.1.0-07 | 当前上限,见第二节 |
| KMP OHOS Support 插件 | 1.0.0 | 读取 local.properties 里的 local.deveco.path |
| 目标设备 | HarmonyOS API 17+ 真机或模拟器 | 必须用华为开发者账号完成自动签名才能安装 |
DevEco 装在非默认路径时,必须在工程根目录的 local.properties 里显式声明(该文件不入库):
local.deveco.path=D\:\\Dev\\Huawei\\DevEco Studio
/
插件只认这一个键;环境变量
TOOL_HOME/OHOS_SDK_HOME不会被读取,漏配会报
Sync failed: DevEco Studio path not found(详见适配问题与解决方案.mdF2)。
0.3 上游地址
| 项 | 地址 |
|---|---|
| 上游仓库 | https://github.com/apollographql/apollo-kotlin |
| 本文所基于的 tag | v4.3.0 |
适配后源码(含 ohos 改动,单 main 分支) | https://atomgit.com/Goway_Hui/Apollo-Kotlin |
适配 diff(相对 v4.3.0) | adapt/patches/apollo-kotlin-4.3.0-ohos.patch |
| 可运行示例 | KMPCMPOHOS @ feat/01-apollo-kotlin |
上游只经
codeload.github.com取源(github.com:443的 git 协议在本机不可达):
curl -sL -o apollo.tar.gz https://codeload.github.com/apollographql/apollo-kotlin/tar.gz/refs/tags/v4.3.0
0.4 CPF 仓库与依赖来源
“CPF”即 CPF-KMP-CMP 社区,本适配从它这里取两样东西:鸿蒙定制 Kotlin 工具链,以及已适配 ohosArm64 变体的传递依赖。
| 用途 | 地址 |
|---|---|
| 组织首页(文档 / 插件 / 已适配库源码) | https://atomgit.com/CPF-KMP-CMP |
| Maven 仓库(Gradle 里要配的那个) | https://maven.eazytec-cloud.com/nexus/repository/maven-public/ |
Maven 浏览页(查某个库有哪些 -1.0.0 定制版本) | https://maven.eazytec-cloud.com/nexus/#browse/browse:maven-releases |
| 三方库总览(上游版本 ↔ 鸿蒙化版本对照表) | CPF 文档 · 三方库 |
| 三方库示例工程 | kmp-thirdlibdemo · kmp-cmp-example |
Gradle 侧只需加一条仓库,后文 3.1 会改到:
maven("https://maven.eazytec-cloud.com/nexus/repository/maven-public/")
## 一、为什么要"适配"
Apollo-Kotlin 是一个标准的多平台库,它在 build-logic 里统一注册编译目标:
// 上游 build-logic/src/main/kotlin/Mpp.kt(改造前)
if (withJvm) { jvm() }
if (enableJs && withJs) { js(IR) { ... } }
if (withWasm) { wasmJs { nodejs() } }
if (enableLinux && withLinux) { linuxX64("linux") }
if (withAndroid) { androidTarget { ... } }
if (enableApple) { appleTargets.forEach { ... } }
没有 ohosArm64。HarmonyOS 上跑的是 Kotlin/Native 产物(.so / klib),
官方 Kotlin 编译器不产出这个目标,必须用定制工具链;库也必须显式注册该目标,
并为每个 expect 声明补上 actual 实现。
所以"适配"就三件事:
二、第一道门槛:版本选型
这是最容易忽略、也最容易卡死的一步。鸿蒙定制 Kotlin 工具链的版本上限决定了能适配哪个上游版本。
查询当前可用版本:
curl -s "https://maven.eazytec-cloud.com/nexus/repository/maven-public/org/jetbrains/kotlin/kotlin-gradle-plugin/maven-metadata.xml" \
| grep -o "<version>[^<]*</version>" | sed 's/<[^>]*>//g' \
| grep -E "^2\.[0-9]+\." | sort -uV | tail
结果(2026-10):
2.2.21-1.1.0-01 ... 2.2.21-1.1.0-07
2.2.21-KBAT-004 ... 2.2.21-KBAT-009
2.2.21-OH.0.1.0-01 ... 2.2.21-OH.0.1.0-07
上限是 2.2.21。对照 Apollo 各版本的 Kotlin 依赖:
| Apollo 版本 | 上游 Kotlin | 结论 |
|---|---|---|
| 5.2.0 / 5.1.0 / 5.0.0 | 2.3.10 | ✗ 超出上限 |
| 4.3.0 | 2.1.20 | ✓ 选用,升级到 2.2.21 |
原则:优先"升上游的 Kotlin 版本",而不是"降上游库版本"。
升级 Kotlin 一般是兼容的;降库版本可能丢掉 API、破坏依赖约束。
最终把 Apollo 4.3.0 的 Kotlin 从 2.1.20 升到 2.2.21-1.1.0-07。
三、改动清单
3.1 构建脚本(4 个文件)
gradle/libraries.toml —— 版本升级
kotlin-plugin = "2.2.21-1.1.0-07" # was 2.1.20
kotlin-plugin-max = "2.2.21" # was 2.1.20
gradle/repositories.gradle.kts —— 加鸿蒙仓库
listOf(pluginManagement.repositories, dependencyResolutionManagement.repositories).forEach {
it.apply {
// OHOS (OpenHarmony) KMP 定制产物仓库
maven("https://maven.eazytec-cloud.com/nexus/repository/maven-public/")
mavenCentral()
...
}
}
build.gradle.kts(根) —— 移除 BCV
binary-compatibility-validator 0.16.3 不认识自定义目标 ohosArm64,
会在配置阶段抛 NPE,必须移除:
// apply(plugin = "org.jetbrains.kotlinx.binary-compatibility-validator")
// configure<kotlinx.validation.ApiValidationExtension> { ... } ← 整块删掉
build-logic/src/main/kotlin/Mpp.kt —— 注册目标
kotlinExtension.apply {
// OHOS 适配:ohosOnly 模式下只保留 ohosArm64 目标,
// 便于在 Windows 上编译/发布(apple/js/wasm 目标在 Windows 上不可构建)
val ohosOnly = providers.gradleProperty("apollo.ohosOnly").orNull == "true"
if (withJvm && !ohosOnly) { jvm() }
if (enableJs && withJs && !ohosOnly) { js(IR) { ... } }
if (withWasm && !ohosOnly) { wasmJs { nodejs() } }
if (enableLinux && withLinux && !ohosOnly) { linuxX64("linux") }
// ---- 新增:鸿蒙目标 ----
if (withOhos) {
ohosArm64 {
binaries {
all {
// 工具链自带 sysroot,含 libhilog_ndk.z.so,只需写库名
linkerOpts("-lhilog_ndk.z")
}
}
}
}
if (withAndroid && !ohosOnly) { androidTarget { ... } }
if (enableApple && !ohosOnly) { appleTargets.forEach { ... } }
configureSourceSetGraph()
configureOhosHierarchy()
}
关键点:linkerOpts 只写 -lhilog_ndk.z。
CPF 官方示例里写的是 ${System.getenv("OHOS_NDK_HOME")}/native/llvm/.../libunwind.a,
但本机 OHOS_NDK_HOME 指向 .../hms/native/BiSheng,拼出来是死路径。
定制工具链自带完整 sysroot(145 个系统库),不需要手动指 NDK 路径。

3.2 源码集层级(最容易踩的坑)
第一版适配时我删掉了手写的 ohosArm64Main.dependsOn(...),因为工具链提示:
Redundant dependsOn edges between Kotlin Source Sets found.
* ohosArm64Main.dependsOn(concurrentMain)
这个提示具有误导性。它抱怨的是"重复挂 concurrentMain"(模板已经挂过了),
不代表 linuxMain 也挂好了。删掉后立刻报错:
e: ApolloAdaptableWith.kt:6:1 Expected ApolloAdaptableWith has no actual declaration in module <commonMain> for Native
而该 actual 明明存在于 linuxMain。结论:
OHOS 工具链的默认层级模板只把
ohosArm64Main挂到concurrentMain(native 通用),
不会挂linuxMain。
所以必须显式挂上(鸿蒙同为 Linux 内核,POSIX 能力一致):
@OptIn(ExperimentalKotlinGradlePluginApi::class)
private fun KotlinMultiplatformExtension.configureOhosHierarchy() {
if (targets.findByName("ohosArm64") == null) return
val ohosMain = sourceSets.findByName("ohosArm64Main") ?: return
val linuxMain = sourceSets.findByName("linuxMain")
if (linuxMain != null) {
if (!ohosMain.dependsOn.contains(linuxMain)) {
ohosMain.dependsOn(linuxMain)
}
} else {
// ohosOnly 模式下没有 linux 目标,直接把源码目录并进来
val dir = project.file("src/linuxMain/kotlin")
if (dir.isDirectory) {
ohosMain.kotlin.srcDir(dir)
}
}
}
挂了之后,ohosArm64Main 里就不要再重复写 linuxMain 已有的 actual,否则 Conflicting overloads。
我最初在 apollo-api 里手抄了 toJson.kt 和 OhosApolloUnsafeCast.kt,
后来全部删掉——它们已由 linuxMain 提供。
3.3 依赖升级(最高频的坑)
编译时报:
Could not resolve com.squareup.okio:okio:3.9.0.
> No matching variant of com.squareup.okio:okio:3.9.0 was found.
The consumer ... attribute 'org.jetbrains.kotlin.native.target' with value 'ohos_arm64'
原因:传递依赖也没有鸿蒙变体。Apollo 依赖的 okio / uuid / coroutines / atomicfu 都得换成
CPF 已适配的定制版本:
atomicfu = "0.31.0-1.0.0"
kotlinx-coroutines = "1.10.2-1.0.0"
kotlinx-datetime = "0.7.1-1.0.0"
okio = "3.16.4-1.0.0"
uuid = { group = "com.benasher44", name = "uuid", version = "0.8.4-1.0.0" }
通用做法:把
libraries.toml里所有版本号搜一遍,能升的全升到 CPF 的-1.0.0线。
但有一个例外:build-logic/ 是 Gradle 的 included build,用 embedded Kotlin 2.0 编译。
如果把 kotlinx-serialization 升到 1.9.1,它的元数据版本是 2.2.0,build-logic 直接编译失败:
e: kotlin-stdlib-2.2.21-0.3.0.jar!/META-INF/kotlin-stdlib.kotlin_module
Module was compiled with an incompatible version of Kotlin.
The binary version of its metadata is 2.2.0, expected version is 2.0.0.
所以 kotlinx-serialization-runtime 保持 1.6.2 不动
(确认过只有 apollo-ast 用它,而 apollo-ast 是构建期工具,不需要 ohos)。
3.4 关闭 -Werror
升依赖引入了上游的 deprecation 警告,而 Apollo 的构建约定里开了 allWarningsAsErrors(true):
e: warnings found and -Werror specified
w: KotlinxTimeAdapters.kt:8:8 'class Instant ...' is deprecated. Use kotlin.time.Instant instead.
适配构建不追求零警告,关掉:
// build-logic/src/main/kotlin/CompilerOptions.kt
allWarningsAsErrors(false) // was true
3.5 手写 ohos actual(6 个文件)
这是真正的"平台实现"工作。逐模块清点 expect 后逐个补:
| 模块 | 文件 | 实现要点 |
|---|---|---|
apollo-mpp-utils | utils.kt | currentTimeMillis() 用 POSIX clock_gettime(CLOCK_REALTIME) |
apollo-adapters | BigDecimal.kt | 纯 Kotlin 十进制实现(鸿蒙无 NSDecimalNumber/java.math.BigDecimal) |
apollo-normalized-cache | Lock.kt | AtomicFu ReentrantLock(照抄 appleMain) |
apollo-normalized-cache-api | -cache-lock-ohos.kt | 同上 |
apollo-runtime | DefaultHttpEngine.ohos.kt | ktor-client-cio 引擎 |
apollo-runtime | WebSocketEngine.ohos.kt ×2 | ktor WebSockets 插件(新旧两套 API) |
BigDecimal 是最费心的一个,因为鸿蒙没有任何现成的大数实现:
actual class BigDecimal internal constructor(
private val unscaled: Long, // 去掉小数点后的整数
private val scale: Int, // 小数位数
) : Number() {
actual fun add(augend: BigDecimal): BigDecimal {
val s = maxOf(scale, augend.scale)
return BigDecimal(rescaledTo(s) + augend.rescaledTo(s), s)
}
actual fun multiply(multiplicand: BigDecimal): BigDecimal =
BigDecimal(unscaled * multiplicand.unscaled, scale + multiplicand.scale)
// ...
}
3.6 手写 HTTP / WebSocket 引擎(最实质的适配)
Apollo 的 native 侧只有 Apple 实现(appleMain),apollo-runtime 连 linuxMain 都没有。
所以鸿蒙的 HTTP / WebSocket 必须新写。这里复用 CPF 已适配的 ktor:
// apollo-runtime/src/ohosArm64Main/.../DefaultHttpEngine.ohos.kt
actual fun DefaultHttpEngine(timeoutMillis: Long): HttpEngine = OhosHttpEngine(timeoutMillis)
private class OhosHttpEngine(private val timeoutMillis: Long) : HttpEngine {
private val client: HttpClient by lazy {
HttpClient(CIO) {
engine { requestTimeout = timeoutMillis }
expectSuccess = false
}
}
override suspend fun execute(request: HttpRequest): HttpResponse {
val ktorResponse = client.request(request.url) {
method = when (request.method) {
HttpMethod.Get -> KtorHttpMethod.Get
HttpMethod.Post -> KtorHttpMethod.Post
}
request.headers.forEach { headers.append(it.name, it.value) }
request.body?.let { body ->
val buffer = Buffer()
body.writeTo(buffer)
setBody(ByteArrayContent(buffer.readByteArray(), ContentType.parse(body.contentType)))
}
}
val builder = HttpResponse.Builder(ktorResponse.status.value)
ktorResponse.headers.entries().forEach { e ->
e.value.forEach { builder.addHeader(e.key, it) }
}
return builder.body(Buffer().write(ktorResponse.readRawBytes())).build()
}
override fun close() { client.close() }
}
WebSocket 部分要点类似,但有两个 ktor API 细节必须注意:
// ① 取响应体用 readRawBytes()(旧名 readBytes 已废弃)
val bytes = ktorResponse.readRawBytes()
// ② webSocketSession 的 url 要用 lambda 形式
client.webSocketSession {
url { takeFrom(newUrl) }
extraHeaders.forEach { header -> this.headers.append(header.name, header.value) }
}
第 ② 点踩过坑:函数参数名 headers 与 HttpRequestBuilder.headers 同名,
lambda 内 headers.append(...) 被解析成了 StringBuilder.append,报一堆候选不匹配。
解决办法是局部改名 + 显式 this。
另外 ktor 版本要单独处理:Apollo 4.3.0 自带 ktor 3.0.0(无 ohos 变体),
而 CPF 适配的是 3.3.3-1.0.0。由于只在 ohosArm64Main 声明,不影响其他平台:
findByName("ohosArm64Main")?.apply {
dependencies {
implementation("io.ktor:ktor-client-core:3.3.3-1.0.0")
implementation("io.ktor:ktor-client-cio:3.3.3-1.0.0")
implementation("io.ktor:ktor-client-websockets:3.3.3-1.0.0")
}
}
四、验证
# 7 个模块全部编译通过
gradlew :apollo-annotations:compileKotlinOhosArm64 \
:apollo-mpp-utils:compileKotlinOhosArm64 \
:apollo-api:compileKotlinOhosArm64 \
:apollo-adapters:compileKotlinOhosArm64 \
:apollo-normalized-cache-api:compileKotlinOhosArm64 \
:apollo-normalized-cache:compileKotlinOhosArm64 \
:apollo-runtime:compileKotlinOhosArm64
结果:
> Task :apollo-annotations:compileKotlinOhosArm64
> Task :apollo-mpp-utils:compileKotlinOhosArm64
> Task :apollo-api:compileKotlinOhosArm64
> Task :apollo-normalized-cache-api:compileKotlinOhosArm64
> Task :apollo-adapters:compileKotlinOhosArm64
> Task :apollo-normalized-cache:compileKotlinOhosArm64
> Task :apollo-runtime:compileKotlinOhosArm64
BUILD SUCCESSFUL

编译只是第一关。把产物打进 HAP 装到真机(nova 14 Ultra,HarmonyOS API 26)后,
四项验证全部通过:

④ 是这轮踩坑的重点:CIO 在 Native 上不支持 TLS,换成 Curl 引擎才真正发得出 HTTPS 请求;
同时网络调用不能放在 UI 线程,否则会触发 APP_INPUT_BLOCK 被系统强杀(详见 03 · 排障 R3)。
五、FAQ
按"为什么会这样 / 我该怎么做"组织。带报错原文的问题在 03 · 排障 有速查表,这里只讲决策与原理。
5.1 版本与依赖
Q1. 为什么不能直接用 JetBrains 官方 Kotlin 编译 ohosArm64?
官方编译器没有这个 target。ohosArm64 是 CPF 定制工具链新增的目标(2.2.21-1.1.0-xx / 2.2.21-KBAT-xxx),它同时改了两处:注册 ohosArm64 目标本身,以及提供对应的 sysroot(145 个 OHOS 系统库)。用官方工具链时 targets.findByName("ohosArm64") 恒为 null,源码集和依赖解析都不会有 ohos 变体。
Q2. 为什么选 Apollo 4.3.0,而不是最新的 5.x?
工具链版本上限卡住上游。5.x 依赖 Kotlin 2.3.10,而 CPF 当前最高只到 2.2.21;4.3.0 依赖 2.1.20,升到 2.2.21 是小版本内升级,兼容风险最低。查询方法见第二节。
Q3. 为什么不反过来「降上游库版本」来迁就工具链?
降版本会丢 API、破坏下游的依赖约束(Apollo 5.x→4.x 有 breaking change),而升 Kotlin 小版本一般兼容。优先级:升工具链版本 > 升上游 Kotlin > 降库版本。只有当上游 Kotlin 超出上限且无法降级时,才退回旧库版本。
Q4. 为什么 -1.0.0 后缀的依赖全都要换?换了会不会引入不兼容?
因为 Gradle 变体匹配是按模块独立的:Apollo 自己要 ohos_arm64 变体,它的传递依赖(okio / uuid / coroutines / atomicfu / datetime)也要。上游原版这些库没有 ohos 变体,解析直接失败。
-1.0.0 是 CPF 在同一上游版本上补加 ohos 目标的产物,API 与上游本版一致,所以是"平移"而非"升级语义"。风险点只有一个:版本号必须与上游本版对齐(如 okio 3.16.4 而不是 3.9.0),否则会带进别的 API 差异,报 No matching variant 之外还会报未解析符号。
Q5. 为什么 kotlinx-serialization 独独保持 1.6.2 不升?
build-logic/ 是 Gradle included build,用 Gradle 内嵌的 Kotlin 2.0 编译。1.9.1 的元数据版本是 2.2.0,2.0 的编译器读不了(Module was compiled with an incompatible version of Kotlin)。而 apollo-ast 是构建期工具,不发布 ohos 产物,保持旧版本零影响。
判据:构建期(included build / buildSrc)用到的依赖,版本受 Gradle 内嵌 Kotlin 约束,不受工具链约束。
5.2 源码集与产物
Q6. 为什么必须手写 ohosArm64Main.dependsOn(linuxMain)?
OHOS 工具链的默认层级模板只把 ohosArm64Main 挂到 concurrentMain(native 通用层),不含 linuxMain。Apollo 把 POSIX 实现(currentTimeMillis、toJson、ApolloUnsafeCast 等)放在 linuxMain,不显式挂就报 Expected X has no actual declaration。
Q7. 工具链提示 Redundant dependsOn edges,我能不能按它说的删掉?
不能。这条提示只说明"某条边已经通过模板存在",不保证你要的那条存在。当时的实际情形是 concurrentMain 重复、linuxMain 缺失,删掉后立刻报 no actual declaration。正确做法是保留显式挂载并加 contains 判重(见 3.2 的代码),让重复的边自动跳过。
Q8. 挂上 linuxMain 后,ohosArm64Main 里还要不要抄一份 actual?
不要。抄了就是 Conflicting overloads——同一个 expect 拿到两份 actual。先挂层级,再只看编译报错缺失的符号,逐个补;已由 linuxMain 提供的(toJson.kt、OhosApolloUnsafeCast.kt)不要再写。
Q9. 为什么 klib 只能放 ohosMain,放 commonMain 不行?
这些产物只发布了 ohosArm64 变体。工程同时有 androidTarget,commonMain 必须对所有目标成立,Gradle 会报 Unresolved platforms: [android, android]。同理,androidMain 也要给同一批 expect 一个占位实现,否则 commonMain 编译不过。
Q10. 为什么发布要跑两遍(平台 + 根模块)?
两遍产出的是不同层级的元数据:publishOhosArm64PublicationToMavenLocal 出平台 klib(apollo-runtime-ohosarm64-4.3.0.klib);publishToMavenLocal 出根模块(apollo-runtime-4.3.0.module)。消费方的变体匹配读的是根模块的 .module 文件,缺了它直接报 Unresolved platforms: [ohosArm64]。
5.3 构建配置
Q11. 为什么非要删掉 binary-compatibility-validator?只关 klib.enabled 不行吗?
BCV 0.16.3 在配置阶段就遍历目标,遇到不认识的 ohosArm64 直接 NPE(extractUnderlyingTarget),此时 klib.enabled = false 还没生效。适配构建不做 klib API 校验,整块移除即可;发布前若要校验 API 兼容性,改用 diff 对比或在上游 CI 跑。
Q12. linkerOpts 为什么只写 -lhilog_ndk.z,不按 CPF 示例拼 NDK 绝对路径?
CPF 示例用 ${System.getenv("OHOS_NDK_HOME")}/native/llvm/.../libunwind.a,前提是那台机器的 OHOS_NDK_HOME 指向完整 NDK。本机它指向 .../hms/native/BiSheng,拼出来是死路径,链接必然失败。定制工具链自带完整 sysroot,-lhilog_ndk.z 由链接器在 sysroot 里解析即可。
Q12b. 为什么 HTTP 引擎从 CIO 换成了 Curl?
CIO 在 Kotlin/Native 上不支持 TLS,HTTPS 会直接抛:
IllegalStateException: TLS sessions are not supported on Native platform.
这也是 Ktor 生态的通用结论(iOS 用 Darwin 引擎,桌面 Native 用 Curl)。OHOS 没有 Darwin,
但 CPF 发布了 ktor-client-curl-ohosarm64,其 cinterop 包内自带
libcurl.a / libssl.a / libcrypto.a(ohosArm64 静态库),可静态链接 TLS。
HttpClient(Curl) {
install(HttpTimeout) { requestTimeoutMillis = timeoutMillis }
expectSuccess = false
}
注意 Curl 引擎没有 CIO 的 engine { requestTimeout = ... },超时要走 HttpTimeout 插件。
WebSocket 仍用 CIO(Curl 引擎不支持 WebSocket),因此
wss://在 OHOS 上仍不可用。
Q13. -Papollo.ohosOnly=true 是干什么的?不加行不行?
Apollo 的构建脚本会注册 jvm/js/wasm/linux/apple/android 全套目标。这些目标里 apple、js、wasm 在 Windows 上不可构建,光配置就会失败。ohosOnly 把它们短路掉,只留 ohosArm64,这样发布 mavenLocal 的流水线才跑得通。Linux/macOS 上不加也能过,但没必要——ohos 产物与它们无关。
Q14. 关掉 -Werror 会不会掩盖真问题?
关了只是不让弃用警告中断构建,警告仍会打印。适配版的目标是"能编、能跑",不是"零警告";但要盯住 w: ...unresolved 之类的非弃用警告,那类通常意味着实际解析出了问题。
5.4 仓库与环境
Q15. 适配后的源码和各处文档链接放在哪?
统一放在 AtomGit:
| 内容 | 地址 |
|---|---|
| 适配后源码 | https://atomgit.com/Goway_Hui/Apollo-Kotlin(单 main) |
| 演示工程 | https://atomgit.com/kmp-cmp-tpc/KMPCMPOHOS(feat/01-apollo-kotlin) |
| 推送地址 | git@atomgit.com:Goway_Hui/Apollo-Kotlin.git |
本文及仓库内其余文档的链接、SSH 地址均使用 atomgit.com 域名,不再出现旧域名。
Q16. ssh -T git@atomgit.com 正常,但 git push 报 Permission denied (publickey)?
Git 自带的 OpenSSH(10.x)与 AtomGit 服务端握手不兼容:ssh -T 能认证,git 的实际传输路径却失败。让 git 改用系统 OpenSSH:
git config --global core.sshCommand "C:/WINDOWS/System32/OpenSSH/ssh.exe"
git ls-remote git@atomgit.com:Goway_Hui/<repo>.git # exit=0 即正常
详见 适配问题与解决方案.md A7。
Q17. 升级工具链版本后,这份适配要重做吗?
不用重做,但要复验三处:① libraries.toml 里 kotlin-plugin / kotlin-plugin-max 同步升;② -1.0.0 定制依赖是否发布了对应的新基线(CPF 仓库查 maven-metadata.xml);③ 源码集默认层级模板是否变化——这是最容易静默出问题的地方,升级后先跑一次全模块 compileKotlinOhosArm64,确认 linuxMain 那条边仍然存在。
Q18. 只适配了 ohosArm64,x86_64 模拟器能跑吗?
本文的产物只有 ohosArm64 变体,未注册也未验证其他 OHOS 目标。真机是 arm64;模拟器上是否有 arm64 镜像取决于你的 DevEco / 设备配置,不在本文验证范围。若需要 x86_64,必须先在 Mpp.kt 注册对应目标,再按同一套流程补 actual、补依赖变体、重发产物。
六、小结
| 改动类别 | 文件数 | 说明 |
|---|---|---|
| 构建脚本 | 4 | 版本、仓库、移除 BCV、注册目标 |
| 模块构建脚本 | 4 | jvmTest 安全引用、wasmJsMain!! 改 ?. |
| 新增 ohos actual | 6 | mpp-utils / adapters / cache / cache-api / runtime |
| 新增 ohos 引擎 | 3 | HTTP ×1、WebSocket ×2 |
三条最重要的经验:
- 先查工具链版本上限,再决定上游库版本——顺序反了会白做
linuxMain不会自动继承,必须显式dependsOn- 传递依赖也要有 ohos 变体,否则换 CPF 定制版
下一篇讲如何在鸿蒙工程里使用 Apollo。
更多推荐


所有评论(0)