## 项目介绍

该项目是一个 Kotlin Multiplatform（KMP）示例工程，目标是在保持一套共享业务逻辑的前提下，分别通过各平台原生方式进行集成与展示，支持 Android / iOS / HarmonyOS 三端。

## 工程结构与关键模块
- `composeApp/`：KMP 共享业务与平台桥接
  - `commonMain/`：平台无关逻辑（如 `appInfo()`）
  - `androidMain/`、`iosMain/`、`ohosArm64Main/`：各平台的 `actual` 实现与桥接代码
  - iOS：
    - `MainViewController.kt` 用于向 Swift 暴露 `UIViewController`
    - `App_ios.kt` 暴露 `iosUiText()`（含 `Arith.add/sub` 结果）
  - Harmony：
    - `OhosEntry.kt` 暴露 `@CName("getKotlinUiText")` 供 NAPI 调用
    - `OhosPlatform.kt` 平台标识实现
- `lib-arith/`：跨平台算术库（add/sub）
  - 仅在 `androidMain` 与 `iosMain`、`ohosArm64Main` 依赖（不放在 `commonMain`）
- `iosApp/`：SwiftUI App，链接 `ComposeApp.framework`
- `harmonyapp/`：ArkTS App，NAPI 桥接 `libkn.so` 与 UI 展示

## 环境准备
- Android Studio：选择 Gradle JDK 为 JDK 17（IDE 内配置，无需写死路径）
- Kotlin/Java 版本建议：
  - Kotlin `jvmToolchain(17)` 用于编译工具链
  - 应用 `jvmTarget` 与 `compileOptions` 建议统一为 Java 11
- iOS：Xcode 15+，建议使用通用 `FRAMEWORK_SEARCH_PATHS`，避免绑定到具体版本目录
- Harmony：DevEco Studio 4.x，ArkTS + NAPI，需可用的 aarch64 交叉工具链

## 构建与运行（Android）
- 运行（AS 中选择 Android 目标设备，正常运行）

## 构建与运行（iOS）
- 生成模拟器框架（arm64 模拟器）
```bash
./gradlew :composeApp:linkDebugFrameworkIosSimulatorArm64
```
- 生成真机框架（arm64 真机）
```bash
./gradlew :composeApp:linkDebugFrameworkIosArm64
```
- Xcode 链接框架
  - Linked Frameworks and Libraries 添加 `ComposeApp.framework`，设置为 “Embed & Sign”
  - 推荐 `FRAMEWORK_SEARCH_PATHS`：
    - `$(SRCROOT)/../composeApp/build/xcode-frameworks/$(CONFIGURATION)/$(PLATFORM_NAME)`
  - 避免使用带版本号目录（例如 `iphonesimulator18.2`），并在 `project.pbxproj` 或 `Config.xcconfig` 中将 `IPHONEOS_DEPLOYMENT_TARGET` 设为你需要的最低版本（如 `17.0`）
- Swift 调用示例（`ContentView.swift`）
```bash
# Swift 中示例调用：
# import ComposeApp
# Text(ComposeAppApp_iosKt.iosUiText())
```

## 构建与运行（HarmonyOS）

- 命令一：仅构建共享库（不拷贝到 Harmony 工程）
  - 作用：编译 KMP 的 Harmony 目标，生成 `libkn.so` 与 `libkn_api.h`
  - 命令：
    ```bash
    ./gradlew :composeApp:linkDebugSharedOhosArm64
    ```
  - 产物目录：`composeApp/build/bin/ohosArm64/debugShared/`
    - 包含 `libkn.so`、`libkn_api.h`
  - 适用场景：仅需产出二进制进行验证或手动集成，不自动同步到 Harmony 项目

- 命令二：构建并发布到 Harmony 工程（自动拷贝）
  - 作用：先执行上面的构建，再把产物拷贝到 `harmonyapp/entry` 便于 ArkTS/NAPI 直接使用
  - 命令：
    ```bash
    ./gradlew :composeApp:publishDebugBinariesToHarmonyApp
    ```
  - 拷贝目标：
    - 头文件：`harmonyapp/entry/src/main/cpp/include/libkn_api.h`
    - 动态库：`harmonyapp/entry/libs/arm64-v8a/libkn.so`
  - 适用场景：希望在 DevEco/ArkTS 侧直接引用最新的 `libkn.so` 与头文件

- 注意事项
  - 两个命令都会依赖 Kotlin/Native 的交叉工具链，若在线下载出现 403，请将工具链离线放到 `~/.konan/dependencies/` 后再执行
  - 建议使用带项目前缀的 Gradle 调用（如 `:composeApp:...`），避免任务名解析歧义
  - 发布任务会校验产物目录是否存在；构建失败或工具链缺失会导致发布任务失败
- 桥接与 UI
  - NAPI（C++）：`napi_init.cpp` 导出 `getKotlinGreeting` 与 `getKotlinUiText`
  - ArkTS：`entry/src/main/ets/libentry.d.ts` 已声明
  - ArkTS 页面调用（`pages/Index.ets`）
```bash
# ArkTS 页面中示例：
# import * as testNapi from 'libentry.so';
# this.kotlinMsg = testNapi.getKotlinUiText();
```
- 拷贝产物到 Harmony 工程
  - `composeApp` 的 Gradle 任务已将 `libkn.so` 与头文件复制到 `harmonyapp/entry/libs/arm64-v8a/` 与 `include/`

## 常见问题与排查
- iOS “import ComposeApp: no such module”
  - 未链接当前架构框架或搜索路径错误。检查 `FRAMEWORK_SEARCH_PATHS` 与 `Embed & Sign`
- iOS 模拟器版本被锁到 18.2
  - 在 `project.pbxproj` 有 `IPHONEOS_DEPLOYMENT_TARGET = 18.2;`；建议迁移到 `Config.xcconfig` 设置通用版本（如 `17.0`）
- KMP iOS C-Interop（UIKit）缺少 Opt-In
  - 在 `MainViewController.kt` 顶部添加 `@file:OptIn(kotlinx.cinterop.ExperimentalForeignApi::class)`
- Harmony NAPI 接口 undefined
  - 确保 `napi_init.cpp` 注册了 `getKotlinUiText`；CMake 包含对应源；`libkn.so` 中存在 `getKotlinUiText` 符号
- Gradle JDK 路径不应写死
  - 删除 `gradle.properties` 的 `org.gradle.java.home`，在 IDE 中选择 JDK 17；在 Gradle 脚本里使用 `jvmToolchain(17)` 保证一致性

## 文案与演示一致性
- Android：`MainActivity` 展示 `appInfo()` + `Arith.add/sub`
- iOS：`App_ios.kt` 提供 `iosUiText()`，Swift 展示同样文案
- Harmony：`OhosEntry.kt` 提供 `ohosUiText()` 与 `getKotlinUiText` NAPI 导出，ArkTS 页面展示同样文案

## 维护建议
- iOS 源集：仅保留 `iosMain` 下的唯一 `Platform.ios.kt`，删除 `iosArm64Main/iosSimulatorArm64Main` 下重复的 `actual`
- 统一工具链：`kotlin { jvmToolchain(17) }` + 应用 `jvmTarget=11`
- 使用通用路径：Xcode 搜索路径使用 `$(PLATFORM_NAME)`，避免绑定具体机型版本