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

一. 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)平台抽象接口设计

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

2)多平台预期声明

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

3)平台专属实现示例

Android 端实现 (androidMain)‌:

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)‌:

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 依赖且配置了原生框架调用时才会生成

    // 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

brew install kdoctor

使用 kdoctor 进行环境检查

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

kdoctor

kdoctor 将检查以下内容:

JDK:是否安装了 Java Development Kit。

Android Studio:是否安装了 Android Studio 和必要的组件。

Xcode:是否安装了 Xcode 和命令行工具。

CocoaPods:是否安装了 CocoaPods(用于管理 iOS 依赖)。

运行 kdoctor 后的示例输出:

$ 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 两个平台的代码,以及一个共享代码模块:

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

跨平台之 KMP / KMM 详解的更多相关文章

  1. kmp算法详解

    转自:http://blog.csdn.net/ddupd/article/details/19899263 KMP算法详解 KMP算法简介: KMP算法是一种高效的字符串匹配算法,关于字符串匹配最简 ...

  2. [转] KMP算法详解

    转载自:http://www.matrix67.com/blog/archives/115 KMP算法详解 如果机房马上要关门了,或者你急着要和MM约会,请直接跳到第六个自然段.    我们这里说的K ...

  3. KMP算法详解(转自中学生OI写的。。ORZ!)

    KMP算法详解 如果机房马上要关门了,或者你急着要和MM约会,请直接跳到第六个自然段. 我们这里说的KMP不是拿来放电影的(虽然我很喜欢这个软件),而是一种算法.KMP算法是拿来处理字符串匹配的.换句 ...

  4. 算法进阶面试题01——KMP算法详解、输出含两次原子串的最短串、判断T1是否包含T2子树、Manacher算法详解、使字符串成为最短回文串

    1.KMP算法详解与应用 子序列:可以连续可以不连续. 子数组/串:要连续 暴力方法:逐个位置比对. KMP:让前面的,指导后面. 概念建设: d的最长前缀与最长后缀的匹配长度为3.(前缀不能到最后一 ...

  5. 数据结构4.3_字符串模式匹配——KMP算法详解

    next数组表示字符串前后缀匹配的最大长度.是KMP算法的精髓所在.可以起到决定模式字符串右移多少长度以达到跳跃式匹配的高效模式. 以下是对next数组的解释: 如何求next数组: 相关链接:按顺序 ...

  6. KMP算法详解&&P3375 【模板】KMP字符串匹配题解

    KMP算法详解: KMP算法是一种改进的字符串匹配算法,由D.E.Knuth,J.H.Morris和V.R.Pratt(雾)提出的. 对于字符串匹配问题(such as 问你在abababb中有多少个 ...

  7. 字符串匹配KMP算法详解

    1. 引言 以前看过很多次KMP算法,一直觉得很有用,但都没有搞明白,一方面是网上很少有比较详细的通俗易懂的讲解,另一方面也怪自己没有沉下心来研究.最近在leetcode上又遇见字符串匹配的题目,以此 ...

  8. KMP算法详解-彻底清楚了(转载+部分原创)

    引言 KMP算法指的是字符串模式匹配算法,问题是:在主串T中找到第一次出现完整子串P时的起始位置.该算法是三位大牛:D.E.Knuth.J.H.Morris和V.R.Pratt同时发现的,以其名字首字 ...

  9. KMP算法详解 --- 彻头彻尾理解KMP算法

    前言 之前对kmp算法虽然了解它的原理,即求出P0···Pi的最大相同前后缀长度k. 但是问题在于如何求出这个最大前后缀长度呢? 我觉得网上很多帖子都说的不是很清楚,总感觉没有把那层纸戳破, 后来翻看 ...

  10. 字符串匹配的KMP算法详解及C#实现

    字符串匹配是计算机的基本任务之一. 举例来说,有一个字符串"BBC ABCDAB ABCDABCDABDE",我想知道,里面是否包含另一个字符串"ABCDABD" ...

随机推荐

  1. cypress 在 typescript 项目中报错找不到 'tslib'

    原文链接:https://blog.jijian.link/2020-08-11/cypress-typescript-cannot-find-module-tslib/ cypress 在 type ...

  2. Kubernetes 编译 kubeadm 修改证书有效期到 100 年

    前言 kubeadm 生成的客户端证书在 1 年后到期.过期后,会导致服务不可用,使用过程中会出现:x509: certificate has expired or is not yet valid. ...

  3. Oracle11g的SGA和PGA设置为多大最合适?

    Oracle官方文档推荐: MEMORY_TARGET=物理内存 x 80% MEMORY_MAX_SIZE=物理内存 x 80% 对于OLTP系统:  SGA_TARGET=(物理内存 x 80%) ...

  4. 独立博客与秘密基地,以及对UI设计中拟物态的怀念

    小时候的秘密基地 哪个人小的时候不想有一个"秘密基地"呢?后来人长大了,心里还有这个小欲望,想有一块属于自己的空间,可以自由装饰,可以藏喜欢的东西,不受社会道德约束,不受规则铁蹄践 ...

  5. Global.asax 转

    备忘: 项目中的Global.asax文件里通常包含这5个方法: Application_Start – web 应用程序最初启动时执行 Application_End – 应用程序关闭时运行 App ...

  6. Docker 实用镜像

    实用镜像 nginx-proxy nginx-proxy sets up a container running nginx and docker-gen. ...

  7. pg获取tree完整的数据

    一个表: DRGCode DRGParend DRGName 这样一个tree表结构. 任意查询string,希望得到一个查询完整的tree.怎么做? SELECT * FROM "DRG& ...

  8. Excel百万数据如何快速导入?

    前言 今天要讨论一个让无数人抓狂的话题:如何高效导入百万级Excel数据. 去年有家公司找到我,他们的电商系统遇到一个致命问题:每天需要导入20万条商品数据,但一执行就卡死,最长耗时超过3小时. 更魔 ...

  9. python tkinker答题工具简易实现

    分享一个简单的python tkinker实现的答题工具,效果参见https://www.bilibili.com/video/BV13e4y1E71d/ 点击查看代码 import tkinter ...

  10. FreeRTOS消息队列传递数组

    1.使用消息队列的发送和接收前,需要先创建消息队列 2.消息队列的深度和大小   深度 就是数组的元素个数   大小 就是整个数组占用的空间大小 消息队列的创建 static void AppObjC ...