跨平台之 KMP / KMM 详解

任何事情,急于求成都是幼稚的幻想,急于求成的结果一定是不成,对此不应该有任何怀疑。

一. KMP 和 Compose Multiplatform

摘要:减少为不同平台编写和维护相同业务逻辑代码所花费的时间,同时又能保留 NA 编程的录活性和优势。

在移动应用开发领域,Kotlin Multiplatform Mobile (KMM) 和 Compose Multiplatform 的结合正在成为一种强大的解决方案。它们不仅解决了传统跨平台开发中的诸多痛点,还提供了许多独特的优势,使得开发者能够更加高效地构建和维护跨平台应用。以下是它的主要优势:

  • 代码复用
    KMM 和 Compose Multiplatform 允许开发者在 Android 和 iOS 之间共享大部分代码,包括业务逻辑和 UI 组件。
  • 性能优化
    与某些其他跨平台框架不同,KMM 生成的代码是直接运行在目标平台的原生环境中的。这意味着开发者可以享受到与原生开发相同的性能和系统级优化。
  • 平台特性和灵活性
    KMM 通过 expect 和 actual 关键字,允许开发者为不同的平台编写特定的实现。这种灵活性使得开发者可以充分利用各个平台的特性,而不会妥协于跨平台的限制。Compose Multiplatform 同样支持这种灵活性,确保 UI 设计可以根据平台的需求进行优化。
  • 一致的开发体验
    Kotlin 作为一种现代语言,拥有简洁的语法和强大的功能特性,深受开发者喜爱。利用 Kotlin 和 Compose Multiplatform,开发者能够在相同的开发环境中进行多平台开发,提升了开发者的体验和生产力。使用 Android Studio 和 Xcode 无缝集成,开发者可以在熟悉的 IDE 中进行跨平台开发和调试。
  • 现代化的 UI 构建
    Compose Multiplatform 基于声明式编程范式,简化了复杂的 UI 构建。开发者可以通过简明的代码定义动态界面,减少了样板代码和 UI 更新的复杂度。这种现代化的 UI 构建方式,不仅使代码更加清晰和易于维护,还提升了开发效率。

使用 KMM 和 Compose Multiplatform,开发团队可以在保证高性能和平台特性的同时,实现代码的最大复用和开发效率的提升。这种结合不仅为项目带来了显著的优势,还为开发者提供了创新和灵活的开发体验。

1. 基础概念

什么是 Kotlin Multiplatform (KMP)?

Kotlin Multiplatform (KMP) 是 JetBrains 提供的一项功能,允许使用 Kotlin 编写可以在多个平台上运行的代码。KMP 的目标是通过共享业务逻辑代码来减少不同平台开发的重复工作。KMP 支持的平台包括但不限于:

JVM:用于服务器端开发以及 Android 开发。

JavaScript:用于前端 Web 开发。

原生平台 (Native):如 iOS、Windows、macOS、Linux 等。

什么是 Kotlin Multiplatform Mobile (KMM)?

Kotlin Multiplatform Mobile (KMM) 是专注于移动平台的一种 KMP 实现。KMM 让开发者能够使用 Kotlin 编写可以在 Android 和 iOS 上运行的共享代码,主要关注点是在移动设备上的应用开发。简单来说,KMM 是 KMP 的一个子集或特化实现,专注于移动开发。

什么是 Compose multiform?

Compose Multiplatform 是 JetBrains 开发的一种跨平台用户界面 (UI) 框架,它基于 Kotlin 和 Jetpack Compose 的设计理念,旨在通过声明式编程范式简化 跨平台 UI 构建

什么是 Kotlin/Native、Kotlin/JVM、Kotlin/JS?与 KMP 的关系?

Kotlin 是一种现代化的编程语言,由 JetBrains 开发,支持多平台开发,包括 JVM、JavaScript 和原生平台。为了更高效地开发跨平台应用,Kotlin 提供了三种主要的编译器后端:Kotlin/JVM、Kotlin/JS 和 Kotlin/Native。

Kotlin/JVM 是最初的 Kotlin 编译器后端,也是最常用的一种。它将 Kotlin 代码编译成可以在 Java 虚拟机 (JVM) 上运行的字节码。由于 Kotlin 与 Java 高度互操作,Kotlin/JVM 可以直接利用现有的 Java 库和框架,使得开发者能够轻松地将 Kotlin 与 Java 项目集成。使用场景有 Android 开发与服务器开发。

Kotlin/JS 将 Kotlin 编译为 JavaScript 代码,从而可以在浏览器或 Node.js 环境中运行。Kotlin/JS 使得前端开发者可以使用 Kotlin 编写网页应用,同时充分利用现有的 JavaScript 库和框架。使用场景是 Web 前端开发。

Kotlin/Native 将 Kotlin 编译为原生二进制代码,可以直接运行在不依赖 JVM 或 JavaScript 引擎的环境中。Kotlin/Native 支持多种平台,包括 iOS、Windows、MacOS、Linux、嵌入式设备等,甚至于 Android、鸿蒙也可以使用 KN 跨平台开发(需要编写 JNI or NAPI 桥接代码)。KMP 结合了 Kotlin/JVM、Kotlin/JS 和 Kotlin/Native 的优势,使开发者能够在统一的代码库中,针对不同平台进行开发,实现跨平台方案。

2. KMP 核心原理

https://www.cnblogs.com/liqw/p/15416758.html

2.1 特定于平台的 API 和实现

expect/actual 机制 :

KMM 里 expect/actual 机制是非常重要的,因为它提供了一种语法技术来解决平台相关的问题。举例来说,当我们需要在业务逻辑中使用设备的 model 号时,我们需要编写特定平台的代码才能实现。这时,expect 就相当于声明一个协议,它定义了我们期望得到的接口或数据,之后各个平台都需要独立地实现这个协议来满足业务需要。

可能会有人认为这样写了两遍,每个平台都写一遍不如让各个平台自己去写。但是,这种方式只需要建设一次,就像一些基础库一样只需要做一次就能在后面被大家共用。这种共用甚至不限于公司界,整个业界都可以共用一组基础库。

基本流程如下:在 commonMain 目录下建立一个 expect 类或 Top-Level 方法 , 类似创建一个协议声明。分别在 androidMain 和 iosMain 目录中,创建与 expect 声明(类名、方法名、参数类型及名称)完全一致的实现,否则编译器会报错。

1)平台抽象接口设计

kotlin 复制代码
interface Platform { val name: String }
  • 作用 ‌:定义跨平台共享的接口规范,声明所有平台必须实现的 name 属性,用于获取当前运行平台的名称(如"Android""iOS")‌。
  • 设计逻辑‌:通过接口强制各平台实现统一功能,保障代码在跨平台调用时的行为一致性‌。

2)多平台预期声明

kotlin 复制代码
expect fun getPlatform(): Platform
  • expect 关键字 ‌:声明一个需由各平台‌具体实现 ‌的公共函数,遵循 Kotlin Multiplatform 的 expect/actual 机制‌。
  • 函数功能 ‌:调用此函数将返回实现了 Platform 接口的平台专属对象,实现‌编译时多态‌‌。

3)平台专属实现示例

‌**Android 端实现 (androidMain)**‌:

kotlin 复制代码
actual fun getPlatform(): Platform = AndroidPlatform()

class AndroidPlatform : Platform {
    override val name: String = "Android ${android.os.Build.VERSION.SDK_INT}"
}
  • actual 关键字 ‌:对应 expect 声明的具体实现,编译时根据目标平台自动匹配‌。
  • 实现细节‌:通过 Android SDK 获取系统版本号,增强平台特性识别能力‌。

‌**iOS 端实现 (iosMain)**‌:

kotlin 复制代码
actual fun getPlatform(): Platform = IosPlatform()

class IosPlatform : Platform {
    override val name: String = UIDevice.currentDevice.systemName()
}
  • 平台交互 ‌:调用 iOS 原生 API UIDevice 获取设备信息,体现平台特定代码隔离原则‌。

4)核心设计模式

  • 分层架构 ‌:将‌平台无关逻辑 ‌置于 commonMain,‌平台相关实现 ‌隔离在 androidMain/iosMain 等目录‌。
  • 关注点分离 ‌:通过接口抽象和 expect/actual 机制,实现业务逻辑与平台特性的解耦,提升代码复用率‌。

该设计是 Kotlin Multiplatform 项目的典型结构,通过标准化的接口与平台适配层,支撑跨平台应用的统一功能开发‌。

2.2 直接访问 iOS Framework 的核心原理

KMM 项目中 iosMain 能直接访问 iOS Framework 的核心原理,主要依赖以下三层技术机制:

2.2.1 跨平台代码分层机制

通过 expect/actual 声明与实现分离:此机制实现‌接口统一声明、平台独立实现‌的架构‌。

2.2.2 CInterop 原生接口绑定

Kotlin/Native 通过 cinterop 工具生成 Objective-C/Swift 绑定的中间层:

1)生成绑定文件‌

  • 扫描 iOS Framework 的 .h 头文件。
  • 自动生成 Kotlin 可调用的 klib 接口文件(包含类/方法映射)‌。

2)Swift 兼容处理

  • Swift 方法需添加 @objc 修饰符,确保可被 Objective-C 运行时识别‌

    @objc class DeviceHelper: NSObject {
    @objc static func getModel() -> String { /.../ }
    }

2.2.3 编译期代码转换

Kotlin/Native 编译器将代码转换为 iOS 可识别的二进制格式:

1)编译阶段‌

  • iosMain 代码会被编译为 ‌Mach-O 格式‌的 Framework 或静态库‌。
  • 自动嵌入 Kotlin/Native 运行时(约 1MB)以支持跨平台特性‌。

2)产物集成

  • 输出 .framework 文件,包含:

    • 编译后的二进制代码。
    • Objective-C 头文件(自动生成)。
    • 资源文件(如有)‌。
  • Xcode 工程直接依赖该 Framework 即可调用‌。

2.2.4 整体交互流程和技术对比

整体交互流程:

复制代码
graph TD
    A[Kotlin Common] -->|expect 声明| B(iosMain)
    B -->|cinterop 绑定| C[iOS Framework]
    C -->|编译为 Mach-O| D(Xcode 工程)
    D -->|动态链接| E(UIKit 等系统框架)

技术优势对比

特性 KMM 实现方式 传统跨平台方案
API 调用方式 直接访问原生 Framework‌ 通过桥接层间接调用
性能损耗 无额外运行时开销(原生二进制)‌ 常有解释器/JIT 损耗
代码复用率 逻辑层 100% 复用,UI 层独立‌ 全栈强制统一

这一设计使得 KMM 在保持原生性能的同时,实现了逻辑代码的跨平台复用‌。

2.3 cinterop 生成中间层时机

Kotlin/Native 的 cinterop 工具生成 Objective-C/Swift 绑定的中间层,其生成时机和触发条件如下:

2.3.1 生成时机

1)编译期动态生成

  • 绑定文件‌不会在新建项目时自动生成 ‌,而是在‌首次执行构建任务 ‌(如运行 ./gradlew build)时触发生成流程‌。
  • 每次修改 .def 配置文件或原生头文件后,重新构建时会‌增量更新绑定文件‌‌。

2)条件触发机制

  • 仅当项目中声明了 cinterop 依赖且配置了原生框架调用时才会生成

    kotlin 复制代码
    // build.gradle.kts 配置示例  
    kotlin {  
        iosX64() {  
            compilations.getByName("main") {  
                cinterops.create("UIKit") {  
                    defFile("src/nativeInterop/cinterop/UIKit.def")  
                }  
            }  
        }  
    }  

    此时才会生成对应的 klib 和头文件‌

2.3.2 生成路径与产物
阶段 产物路径 文件类型
初始生成 build/bin/native/cinterop/ .klib (Kotlin库)
编译后集成 build/bin/iosX64/debugFramework/ .framework (二进制)
头文件映射 build/generated/cinterop/ .h (Objective-C头文件)‌
2.3.3 生成流程对比
项目状态 绑定文件状态 触发动作
新建空项目 ❌ 未生成 需手动配置 cinterop
配置原生依赖后 ✅ 生成在构建目录 执行 Gradle 构建任务
更新头文件/配置后 ✅ 增量更新 重新编译‌
2.3.4 技术实现原理

1)‌构建管道集成 ‌:cinterop 作为 Kotlin/Native 编译管道的前置步骤,通过 Gradle 插件与构建系统深度集成‌。

复制代码
graph LR  
    A[Gradle Task] --> B(cinterop 解析 .def 文件)  
    B --> C(生成 .klib 和 .h)  
    C --> D(Kotlin/Native 编译)  

2)动态适配机制 ‌:当检测到 src/nativeInterop/cinterop 目录下的 .def 配置文件时,自动注册生成任务‌。

2.3.5 总结
  • 非预生成‌:绑定文件不会在新建项目时预生成,需通过构建任务触发。
  • 按需生成 ‌:仅在声明特定平台(如 iosMain)且配置原生依赖时生成‌。
  • 持续更新‌:头文件或配置变更后,通过重新编译实现动态更新‌

二. KMM 环境搭建

1. KDoctor

kdoctor 是一个用于验证 Kotlin Multiplatform Mobile (KMM) 开发环境是否正确配置的命令行工具。它会检查系统上的各种依赖和配置,确保已经安装并正确配置了所有必要的软件,例如 Android Studio、Xcode、CocoaPods 等。如果是第一次设置 KMM 环境,强烈建议使用 kdoctor 来确认一切都已正确配置。

安装 kdoctor

对于 macOS 系统:

确保 Homebrew 已安装 ,安装 kdoctor

shell 复制代码
brew install kdoctor  

使用 kdoctor 进行环境检查

安装完 kdoctor 后,通过以下命令检查 KMM 开发环境:

shell 复制代码
kdoctor  

kdoctor 将检查以下内容:

JDK:是否安装了 Java Development Kit。
Android Studio:是否安装了 Android Studio 和必要的组件。
Xcode:是否安装了 Xcode 和命令行工具。
CocoaPods:是否安装了 CocoaPods(用于管理 iOS 依赖)。

运行 kdoctor 后的示例输出:

csharp 复制代码
$ kdoctor  
[ ✓ ] Checking the Java version (11.0.8).   
[ ✓ ] Checking the Android Studio installation.   
[ ✓ ] Checking the Xcode installation.   
[ ✓ ] Checking the CocoaPods installation.   
Conclusion:
  ✓ Your operation system is ready for Kotlin Multiplatform Mobile Development!

如果 kdoctor 报告某些组件未正确安装或配置,按照指导信息进行相应的操作来解决问题。在这个示例输出中,kdoctor 表明所有必要的软件都已正确安装,已准备好进行 KMM 开发。

2. Kotlin Multiplatform Plugin

在 Android Studio 中安装 Kotlin Multiplatform 插件:打开 Android Studio,进入 Settings -> Plugins,搜索并安装 Kotlin Multiplatform 插件,重启 Android Studio 以激活插件。

三. 项目构建和解析

https://blog.csdn.net/logicsboy/article/details/128856861

1. 新建 KMM 项目

打开 Android Studio,选择 New Project。在项目模板中,选择 Kotlin Multiplatform App。配置项目名称、保存路径和包名。

2. 项目架构和配置

生成的 KMM 项目包含 Android 和 iOS 两个平台的代码,以及一个共享代码模块:

bash 复制代码
Kmm/  
 ├── .gradle/ # 构建缓存文件
 ├── .idea/ # IDE 配置和元数据
 ├── android/ # Android 壳工程
 ├── gradle/  # gradle 环境管理
 ├── ios/     # iOS 壳工程
 ├── shared/  # 共享代码(业务、UI组件、资源)模块
 │   ├── build/
 │   ├── src/  
 │   │   ├── commonMain/ # 共享逻辑  
 │   │   ├── androidMain/  # Android 平台代码  
 │   │   ├── iosMain/     # iOS 平台代码  
 │   ├── build.gradle.kts
 │   ├── shared.podspec
 ├── .gitignore/ # Git 配置文件
 ├── build.gradle.kts/ # Gradle 构建工具的核心配置文件
 ├── gradle.properties/ # Gradle 构建工具的核心配置文件
 ├── gradlew/ # Gradle Wrapper 的启动脚本
 ├── gradlew.bat/ # Gradle Wrapper 的启动脚本
 ├── local.properties/ # 存储本地敏感配置禁止提交到版本控制
 └── settings.gradle.kts/ # Gradle 构建系统的核心配置文件

.gradle 文件夹是 ‌Gradle 构建工具‌在运行过程中生成的缓存和临时文件目录,主要用于加速构建流程和管理项目依赖。

.idea IDE 配置和元数据,Android Studio 基于 IntelliJ IDEA 开发,所有项目(包括 KMM)在首次打开时都会自动生成 .idea 目录,用于加载和存储配置‌。

android 移动安卓壳工程。

gradle gradle 环境管理。

  • gradle-wrapper.jar ‌:Gradle 环境启动器,实现版本自动化管理 ‌。负责根据 gradle-wrapper.properties 中定义的版本自动下载并安装指定版本的 Gradle‌。
  • ‌**gradle-wrapper.properties**‌:定义所需的 Gradle 版本和下载源,保障跨环境一致性。

ios 移动 iOS 壳工程。

share 共享代码模块,目前仅包含业务逻辑,还可以添加 UI 组件、资源等。

.gitignore 是 Git 版本控制系统中一个 ‌纯文本配置文件 ‌,用于指定 Git 仓库中需要 ‌永久忽略跟踪 ‌ 的文件或目录。它的核心作用是 ‌过滤无需纳入版本控制的文件‌(如临时文件、编译产物、本地环境配置等),避免这些文件被意外提交到仓库中。

build.gradle.kts

  • KMM(Kotlin Multiplatform Mobile)项目中,build.gradle 文件是 ‌Gradle 构建工具 ‌的核心配置文件,用于定义项目的构建规则、依赖关系和插件设置。

gradle.properties

  • 在 KMM(Kotlin Multiplatform Mobile)项目中,gradle.properties 文件是 ‌Gradle 构建工具的核心配置文件‌,用于定义全局属性、控制构建行为以及优化构建性能。

.gradlew .gradlew.bat

  • 在新建 Kotlin Multiplatform Mobile (KMM) 项目时,生成的 ‌**.gradlew** ‌(Unix/Linux/macOS)和 ‌**.gradlew.bat** ‌(Windows)文件是 ‌Gradle Wrapper 的启动脚本‌。它们的作用是统一项目的构建环境,确保开发者无需预先安装特定版本的 Gradle,也能正确构建项目。

local.properties 存储本地敏感配置禁止提交到版本控制。

settings.gradle

  • 在 Kotlin Multiplatform Mobile (KMM) 项目中,settings.gradle 是 ‌Gradle 构建系统的核心配置文件 ‌,主要负责定义项目结构、管理子模块和配置构建行为‌‌。

四. 配置文件详解

1. build.gradle

在 KMM(Kotlin Multiplatform Mobile)项目中,build.gradle 文件是 ‌Gradle 构建工具 ‌的核心配置文件,用于定义项目的构建规则(逻辑)、模块级依赖关系和插件设置、任务等构建逻辑,属于代码的一部分。以下是它在 KMM 项目中的具体作用:定义构建逻辑、依赖关系。

1.1 build.gradle 的作用

Gradle 使用 build.gradle 文件来配置:

  • 项目级设置‌:定义整个项目的构建规则、公共插件、仓库和依赖版本。
  • 模块级设置‌:针对每个子模块(如共享模块、Android App、iOS 框架)配置构建规则。
  • 多平台支持‌:声明 Kotlin Multiplatform 的目标平台(Android、iOS、JVM 等)。
  • 依赖管理‌:声明项目所需的库(如 Kotlin 标准库、第三方库)。

1.‌2 KMM 项目的典型结构

一个 KMM 项目通常包含以下 build.gradle 文件。

1.2.1 项目根目录的 build.gradle
  • 作用‌:全局配置,定义构建工具、以及所有子模块共享的规则。

  • ‌示例:

    复制代码
    // 根项目的 build.gradle
    // 构建工具本身,构建初始化阶段
    buildscript {
        repositories {
            google()
            mavenCentral()
        }
        dependencies {
            // 定义全局使用的 Gradle 插件版本(如 Android 插件、Kotlin 插件)
            classpath "com.android.tools.build:gradle:7.0.4"
            classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:1.6.10"
        }
    }
    
    // 所有子模块共享的配置,配置模块的业务依赖仓库地址,项目配置阶段。项目模块的实际依赖(如 implementation、api)应写在‌模块级‌ build.gradle 中,而非 allprojects 块内
    allprojects {
        repositories {
            google()
            mavenCentral()
        }
    }
    
    // 根项目自身‌(非子模块)	根项目需单独使用的插件或依赖	根项目解析阶段。若根项目无特殊依赖需求,可省略单独 repositories 块,避免冗余
    repositories {
        mavenCentral()
    }
1.2.2 共享模块的 build.gradle
  • 作用‌:配置跨平台代码的构建规则(如 Android 和 iOS 的共享逻辑)。

  • ‌示例:

    复制代码
    // 共享模块的 build.gradle
    plugins {
        id 'org.jetbrains.kotlin.multiplatform'
    }
    
    // 定义目标平台:声明编译目标、启用多平台特性、配置平台专属依赖
    kotlin {
        // 定义多平台目标
        android()  // Android 平台
        iosArm64 { // iOS 设备(ARM64)
            binaries.framework { // 生成 iOS 框架
                baseName = "Shared"
            }
        }
        sourceSets {} // 源集配置
    }
    
    // Android 特定配置
    android {
        compileSdkVersion 31
        defaultConfig {
            minSdkVersion 21
            targetSdkVersion 31
        }
    }
    
    // 依赖声明
    dependencies {
        // 公共依赖(所有平台共享)
        commonMain.dependencies {
            implementation "org.jetbrains.kotlin:kotlin-stdlib-common"
        }
        // Android 专属依赖
        androidMain.dependencies {
            implementation "org.jetbrains.kotlin:kotlin-stdlib"
        }
    }
1.2.3 Android App 模块的 build.gradle
  • 作用‌:配置 Android 应用的构建规则。

  • ‌示例:

    复制代码
    plugins {
        id 'com.android.application'
        id 'kotlin-android'
    }
    
    android {
        compileSdk 31
        defaultConfig {
            applicationId "com.example.kmmapp"
            minSdk 21
            targetSdk 31
        }
    }
    
    dependencies {
        implementation project(":shared")  // 依赖共享模块
        implementation "androidx.core:core-ktx:1.7.0"
    }
1.2.4 iOS 模块的配置‌

说明 ‌:iOS 代码通常通过共享模块生成的框架(.framework)集成到 Xcode 项目,无需单独的 build.gradle

‌1.3 关键配置解析‌

1)多平台目标声明

通过 kotlin { ... } 块定义支持的平台:

复制代码
kotlin {
    android()       // Android 平台
    iosArm64()      // iOS 真机 (ARM64)
    iosSimulatorArm64() // iOS 模拟器 (Apple Silicon)
    jvm()           // JVM 平台(可选)
}

2) 依赖分类‌\定义依赖项

KMM 支持按平台细分依赖:

复制代码
dependencies {
    // 公共依赖(所有平台共享)
    commonMain.dependencies {
        implementation "io.ktor:ktor-client-core:2.0.0"
    }
    // Android 专属依赖
    androidMain.dependencies {
        implementation "io.ktor:ktor-client-android:2.0.0"
    }
    // iOS 专属依赖
    iosMain.dependencies {
        implementation "io.ktor:ktor-client-ios:2.0.0"
    }
}

3) iOS 框架生成

配置共享模块生成 iOS 可用的框架:

复制代码
kotlin {
    iosArm64 {
        binaries.framework {
            baseName = "Shared"  // 框架名称
            export(project(":shared")) // 导出其他模块(可选)
        }
    }
}

4) 定义插件 Plugins

复制代码
plugins {
    id("com.android.application")
    kotlin("android")
}

1.‌4 常见问题与解决

1) 依赖解析失败

  • 表现 ‌:Could not resolve ... 错误。

  • ‌解决:

    • 检查仓库是否包含 google()mavenCentral()
    • 确保网络可以访问仓库(国内可尝试阿里云镜像)。

2) 插件版本冲突

  • 表现 ‌:Unsupported Kotlin plugin version

  • ‌解决:统一 Kotlin 插件版本:

    复制代码
    // 根项目的 build.gradle
    classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:1.6.10"

3) iOS 构建失败

  • 表现 ‌:Framework not found

  • ‌解决‌:

    • 运行 ./gradlew :shared:packForXcode 重新生成框架。
    • 在 Xcode 中清理构建缓存(Product > Clean Build Folder)。

1.‌5 总结‌

build.gradle 在 KMM 项目中是构建流程的核心控制器‌,负责:

  1. 定义多平台目标和编译规则。
  2. 管理跨平台依赖。
  3. 集成 Android 和 iOS 的构建配置。
  4. 生成 iOS 框架供 Xcode 使用。

通过合理配置 build.gradle,你可以实现一套代码在 Android 和 iOS 之间的高效共享,同时保持平台特定逻辑的灵活性。

2. gradle.properties

在 KMM(Kotlin Multiplatform Mobile)项目中,gradle.properties 文件是 ‌Gradle 构建工具的核心配置文件 ‌,用于定义全局属性(变量)、控制构建环境(Gradle 运行参数,主要用于定义行为和优化构建性能)。它在 Android Studio 项目中扮演以下关键角色。

2.1 ‌配置 Gradle 构建环境

通过 gradle.properties,你可以调整 Gradle 本身的运行参数:

  • ‌JVM 内存分配:优化构建速度,避免内存溢出。

    复制代码
    # 增加 Gradle 堆内存
    org.gradle.jvmargs=-Xmx4096m -Dfile.encoding=UTF-8
  • ‌启用构建缓存‌:加速重复构建。

    复制代码
    # 开启缓存
    org.gradle.caching=true
  • ‌并行执行和多项目构建:

    复制代码
    # 并行执行任务
    org.gradle.parallel=true
    # 多项目构建优化
    org.gradle.configureondemand=true

2.2 ‌定义项目全局变量

gradle.properties 中定义的变量,可以在所有模块的 build.gradle.ktsbuild.gradle 文件中直接引用,方便统一管理版本号和通用配置:

复制代码
# 定义公共版本号
kotlin_version=1.8.21
androidGradlePlugin_version=7.4.2

build.gradle.kts 中使用:

复制代码
plugins {  	  kotlin("multiplatform").version(project.property("kotlin_version") as String)
}

2.3 ‌控制 KMM 多平台构建行为

KMM 项目依赖 Kotlin/Native 编译器,gradle.properties 可以配置 Native 编译参数:

复制代码
# 启用 Kotlin/Native 内存模型(新版本默认启用)
kotlin.native.binary.memoryModel=strict
# 禁用 iOS 模拟器 arm64 目标(解决 M1/M2 芯片兼容性问题)
kotlin.native.disableCompilerDaemon=true

2.4 ‌管理 Android 和 iOS 构建配置

  • ‌Android 构建优化:

    复制代码
    # 启用 Android Jetpack Compose
    android.enableCompose=true
    # 禁用不必要的 Lint 检查
    android.enableBuildCache=true
  • ‌iOS 构建配置:

    复制代码
    # 指定 Xcode 兼容版本
    kotlin.ios.teamId=XXXXXXXXXX

2.‌5. ‌配置代理和仓库镜像

解决国内依赖下载慢的问题:

复制代码
# 使用阿里云镜像加速
systemProp.http.proxyHost=mirrors.aliyun.com
systemProp.http.proxyPort=80
systemProp.https.proxyHost=mirrors.aliyun.com
systemProp.https.proxyPort=80

2.6 ‌启用实验性功能

对于 KMM 或 Kotlin 的实验性特性,需在此显式启用:

复制代码
# 启用 Kotlin 新内存管理器(跨平台内存共享)
kotlin.native.enableExperimentalMemoryManager=true
# 启用 Jetpack Compose Multiplatform
org.jetbrains.compose.experimental.kotlin.multiplatform=true

2.7 ‌解决常见构建问题

通过 gradle.properties 快速修复构建错误:

  • ‌Kotlin/Native 编译器版本冲突:

    复制代码
    kotlin.native.version=1.8.21
  • ‌禁用 Precompiled Script Plugins(旧版本 Gradle 兼容):

    复制代码
    org.gradle.unsafe.allow-incompatible-plugins=false

2.8 文件位置与优先级‌

  • 项目级 ‌:<project-root>/gradle.properties
    仅影响当前项目。
  • 全局级 ‌:~/.gradle/gradle.properties
    影响所有 Gradle 项目(谨慎使用)。

2.9 KMM 项目典型配置示例

复制代码
# Gradle 配置
org.gradle.jvmargs=-Xmx4096m -Dfile.encoding=UTF-8
org.gradle.caching=true

# Kotlin 版本
kotlin_version=1.8.21

# Android 配置
android.useAndroidX=true
android.enableCompose=true

# KMM/Native 配置
kotlin.native.binary.memoryModel=strict
kotlin.mpp.enableGranularSourceSetsMetadata=true

# 国内镜像加速
systemProp.http.proxyHost=mirrors.aliyun.com
systemProp.https.proxyHost=mirrors.aliyun.com

注意事项:

  1. 键值对格式 ‌:必须使用 key=value 格式,且不能有多余的空格。
  2. 类型限制 ‌:所有值均为字符串,需在 build.gradle.kts 中按需转换类型。
  3. 版本兼容性 ‌:部分属性(如 kotlin.native.binary.memoryModel)需与 Kotlin 版本匹配,否则构建会失败。

通过合理配置 gradle.properties,你可以显著提升 KMM 项目的构建性能和跨平台开发体验。

3. local.properties

local.properties 是本地开发环境专属的配置文件‌,主要用于存储与开发者机器强相关的路径、密钥等敏感信息,避免将这些内容暴露在版本控制中(禁止提交到版本控制)。以下是其核心功能与使用规范:

3.1 核心作用‌

1)配置本地开发环境路径
  • 定义 Android SDK、NDK 的本地路径(不同开发者机器路径不同)‌。

    复制代码
    sdk.dir=/Users/xxx/Library/Android/sdk  
    ndk.dir=/Users/xxx/Library/Android/ndk  
  • 用于 Gradle 构建时自动识别 Android 开发环境依赖‌。

2)存储敏感信息‌
  • 本地调试密钥路径及密码‌:

    复制代码
    debug.keystore=/path/to/debug.keystore  
    keyAlias=debug  
    keyPassword=123456  
    storePassword=123456  
  • 私有 API 密钥或其他环境变量(如测试服务器地址)‌。

3)隔离团队协作差异
  • 避免因开发者本地环境差异(如 SDK 路径)导致构建失败,文件默认不提交至 Git 等版本控制系统‌。

3.2 典型配置内容

配置项 示例值 用途
sdk.dir /Users/xxx/Library/Android/sdk 指定 Android SDK 安装路径‌。
ndk.dir /Users/xxx/Library/Android/ndk/5.2.9 指定 NDK 路径(如需使用 JNI/Native 代码)‌。
debug.keystore /path/to/debug.keystore 本地调试 APK 的签名文件路径‌。
custom.api.key your_private_key 自定义 API 密钥(如地图服务、支付 SDK)‌。

3.3 ‌在 KMM 项目中的使用方式

1)‌读取配置
  • 在 build.gradle 中通过代码读取配置(以 Android 模块为例)‌:

    复制代码
    def localProperties = new Properties()  
    localProperties.load(new FileInputStream(rootProject.file("local.properties")))  
    
    android {  
        signingConfigs {  
            debug {  
                storeFile file(localProperties["debug.keystore"])  
                storePassword localProperties["storePassword"]  
                keyAlias localProperties["keyAlias"]  
                keyPassword localProperties["keyPassword"]  
            }  
        }  
    }  
2)动态注入环境变量
  • 通过 Gradle 参数传递 local.properties 中的值到代码中(如 API 密钥)‌:

    复制代码
    android {  
        defaultConfig {  
            buildConfigField "String", "API_KEY", "\"${localProperties["api.key"]}\""  
        }  
    }  

    在代码中通过访问:

    复制代码
    BuildConfig.API_KEY

3.4 ‌最佳实践

  1. ‌禁止提交至版本控制

    local.properties 加入 .gitignore,防止敏感信息泄露‌。

  2. ‌提供模板文件

    ‌创建 local.properties.template 并提交,指导团队成员复制后填写本地路径‌。

  3. ‌统一环境管理

    ‌团队协作时,通过文档说明配置项含义及填写规范(如 SDK 版本要求)‌。

3.5 与 gradle.properties 的区别

对比项 local.properties gradle.properties
作用范围 仅本地环境生效 全局项目生效(所有开发者共享)‌。
典型内容 SDK 路径、密钥等敏感信息 JVM 内存、构建缓存开关、插件版本‌。
是否共享

总结 ‌:local.properties 是 KMM 项目中用于隔离本地环境差异的核心文件,通过存储敏感信息和机器特定路径,确保团队协作时构建流程的稳定性和安全性‌

4. settings.gradle

在 Kotlin Multiplatform Mobile (KMM) 项目中,settings.gradle 是 ‌Gradle 构建系统的核心配置文件 ‌,主要负责定义项目结构、管理子模块和配置构建行为‌‌。以下是其核心作用:

4.1 声明项目包含的模块

  • ‌核心功能:通过 include 函数明确项目中包含哪些子模块(如共享代码模块、Android/iOS 平台模块)‌。示例代码‌(KMM 典型配置):

    复制代码
    // 包含共享模块、Android 和 iOS 平台模块
    include ':shared', ':androidApp', ':iosApp'
  • 多平台适配 ‌:在 KMM 中,通常将跨平台逻辑放在 shared 模块,并通过 include 声明其与平台模块的关联‌。

4.2 定义模块路径

  • ‌调整模块路径:若模块不在默认路径下(如将 iOS 模块放在 ios 目录),需通过 project 函数指定路径‌。示例:

    复制代码
    include ':shared', ':androidApp'
    // 指定 iOS 模块路径
    project(':iosApp').projectDir = new File('ios/application')

4.3 配置插件和仓库

  • ‌插件版本管理:在 KMM 中,需统一 Kotlin 插件版本以兼容多平台构建‌。示例:

    复制代码
    pluginManagement {
        repositories {
            google()
            mavenCentral()
            gradlePluginPortal()
        }
        // 指定 Kotlin 和 Android 插件版本
        plugins {
            id 'org.jetbrains.kotlin.multiplatform' version '1.9.20'
            id 'com.android.application' version '8.1.0'
        }
    }

4.4 管理依赖解析策略

  • ‌统一依赖仓库:声明全局仓库地址(如 Maven Central、Google 仓库),确保所有模块使用相同的依赖源‌。示例‌:

    复制代码
    dependencyResolutionManagement {
        repositories {
            google()
            mavenCentral()
        }
    }

4.5 KMM 项目中的特殊作用

  • 多平台模块协调 ‌:确保共享模块(shared)与平台模块(androidAppiosApp)的依赖关系正确传递‌。
  • 构建环境隔离‌:通过插件管理避免不同平台(如 Android 和 iOS)的构建冲突‌。

总结:settings.gradle 在 KMM 项目中是多模块和多平台构建的基石‌,通过声明模块、管理路径和统一配置,确保跨平台代码与原生模块的高效整合‌。其配置直接影响 Gradle 如何识别和组织项目结构,是跨平台开发的关键文件之一。

5. gradlew

在新建 Kotlin Multiplatform Mobile (KMM) 项目时,生成的 ‌**.gradlew** ‌(Unix/Linux/macOS)和 ‌**.gradlew.bat** ‌(Windows)文件是 ‌Gradle Wrapper 的启动脚本‌。它们的作用是统一项目的构建环境,确保开发者无需预先安装特定版本的 Gradle,也能正确构建项目。以下是详细解析:

5.1 Gradle Wrapper 的核心作用

  • 环境一致性 ‌:无论开发者本地安装的 Gradle 版本是什么,项目都通过 Wrapper 使用 ‌**gradle-wrapper.properties**‌ 中指定的 Gradle 版本进行构建,避免版本冲突。
  • 零配置运行‌:新克隆项目的开发者无需手动安装 Gradle,直接运行 Wrapper 脚本即可自动下载并配置正确的 Gradle 版本。

5.2 文件的作用‌

文件名 平台 功能
gradlew Unix/Linux/macOS Shell 脚本,用于执行 Gradle 命令(如 ./gradlew build
gradlew.bat Windows 批处理脚本,功能同上(如 gradlew.bat build
gradle/wrapper/ 目录 所有平台 包含 Wrapper 的核心文件(如 gradle-wrapper.jargradle-wrapper.properties

5.3 核心文件解析‌

1)‌**gradle-wrapper.properties**‌

位于 gradle/wrapper/gradle-wrapper.properties,定义了 Gradle 的下载地址和版本‌:

复制代码
# 指定使用的 Gradle 发行版类型(通常是 'bin' 或 'all')
distributionType=bin
# 指定 Gradle 版本(必须与项目兼容)
distributionUrl=https\://services.gradle.org/distributions/gradle-8.4-bin.zip
  • ‌**bin**‌:仅包含运行时(体积小,适合大多数场景)。
  • ‌**all**‌:包含文档和源码(适用于需要调试 Gradle 的场景)。

2)‌**gradle-wrapper.jar**‌

位于 gradle/wrapper/gradle-wrapper.jar,是 Wrapper 的核心实现,负责 ‌下载并安装指定版本的 Gradle‌。

5.4. 如何使用 Wrapper 脚本?

1)‌Unix/Linux/macOS

复制代码
# 运行构建命令
./gradlew build

# 清理构建缓存
./gradlew clean

# 更新 Gradle 版本(修改 gradle-wrapper.properties 后)
./gradlew wrapper --gradle-version=8.5

2)Windows

复制代码
# 运行构建命令
gradlew.bat build

# 清理构建缓存
gradlew.bat clean

5.5 为何需要提交这些文件到版本控制?

  • 确保一致性‌:所有开发者使用相同的 Gradle 版本和配置。
  • 简化协作‌:新成员无需手动安装或配置 Gradle,直接运行 Wrapper 即可。

5.6 常见问题‌

1)‌Q1:gradlew 权限被拒绝?

  • ‌解决方法:赋予执行权限:

    复制代码
    chmod +x gradlew

2)Q2:如何更新 Gradle 版本?

  • 修改 gradle-wrapper.properties 中的 distributionUrl

  • 运行 Wrapper 任务以下载新版本:

    复制代码
    ./gradlew wrapper --gradle-version=8.5

3)Q3:gradlew 文件被误删怎么办?

  • ‌恢复方法:重新生成 Wrapper;

https://coderyuan.com/2021/05/28/KMM-2/

https://cloud.tencent.com/developer/article/1909223

https://news.qq.com/rain/a/20230324A04YF900