最近在 Kotlin 生态圈里,一个不大不小的变动引起了开发者的广泛讨论:JetBrains 宣布其实验性的项目构建工具Amper将停止开发,其核心功能与理念将逐步整合到Kotlin Toolchain中。对于很多刚开始接触 Amper,或者还在观望 Kotlin 多平台项目构建方案的开发者来说,这个消息可能有些突然,甚至带来了一些困惑。
本文旨在为你彻底梳理清楚这场“权力更迭”的来龙去脉。我们将从 Amper 的诞生与愿景讲起,分析其为何未能“登基”,并深入探讨 Kotlin Toolchain 将如何接过构建生态的接力棒。无论你是 Kotlin 新手,还是正在为复杂的 Gradle 配置而头疼的资深开发者,这篇文章都将帮助你理解 Kotlin 构建工具的未来方向,并为你提供平滑过渡的实战指南。
1. 背景与核心概念:从 Amper 的雄心到 Toolchain 的整合
在深入技术细节之前,我们有必要先理解几个关键角色。
1.1 什么是 Amper?
Amper 是 JetBrains 推出的一款实验性项目构建工具。它的核心目标非常明确:简化 Kotlin 多平台(KMP)项目的配置体验。
如果你使用过传统的 Gradle 来配置 Kotlin Multiplatform 项目,一定会对其中繁琐的build.gradle.kts脚本印象深刻。你需要手动声明各个目标平台(JVM、JS、Native iOS、Native Android 等)、配置依赖关系、处理变体,代码往往冗长且容易出错。Amper 试图用更声明式、更简洁的YAML 格式清单文件(module.yaml)来取代复杂的 Gradle 脚本。
一个简单的 Amper 模块配置可能长这样:
# module.yaml product: com.example.mylib type: lib platforms: [jvm, android, iosArm64] dependencies: - org.jetbrains.kotlinx:kotlinx-coroutines-core:1.8.0这种配置方式直观易懂,极大降低了多平台项目的入门门槛。Amper 在底层仍然使用 Gradle 作为构建引擎,但它提供了一层更友好的抽象。
1.2 什么是 Kotlin Toolchain?
Kotlin Toolchain 并非一个全新的独立工具,而是一个概念和工具的集合。它指的是 Kotlin 编译器、标准库、以及一系列用于开发、构建、测试和运行 Kotlin 应用程序的周边工具链。
当我们说“功能整合到 Kotlin Toolchain”,通常意味着:
- Kotlin 编译器本身将集成更多构建相关的智能功能(如更智能的平台检测、依赖管理)。
- JetBrains IDE(如 IntelliJ IDEA)将提供更强大的原生支持,减少对外部复杂构建脚本的依赖。
- Gradle 的 Kotlin DSL 和插件将持续进化,吸收 Amper 的优秀设计理念,使其变得更易用。
简单说,Amper 是一个试图“替代”Gradle前端体验的独立项目,而 Kotlin Toolchain 的进化是增强现有生态(主要是Gradle+Kotlin插件+IDE)的核心能力。
1.3 为什么是“已死”与“登基”?
JetBrains 的官方公告解释了这一决策:虽然 Amper 在简化配置方面取得了成功,证明了声明式配置的可行性,但维护两套构建系统(Gradle 和 Amper)会给社区和开发者带来巨大的分裂和负担。
- 分裂生态:库作者需要同时支持 Gradle 和 Amper 两种配置方式。
- 维护成本:JetBrains 需要投入双倍资源来维护和演进两套系统。
- 用户困惑:新开发者面临选择困难,不确定该学哪一套。
因此,最合理的路径不是另起炉灶,而是“取其精华,去其糟粕”,将 Amper 中经过验证的优秀思想(如声明式模块定义、简化的平台配置)反向整合到主流的 Kotlin Gradle 插件和 IDE 中。这就是所谓的“Amper 已死,其精神在 Kotlin Toolchain 中重生”。
2. 环境准备与版本说明
在探讨具体变化和实战之前,我们先明确本文涉及的环境。由于变化正在发生,本文重点在于展示配置思路和未来方向,请根据你实际使用的 Kotlin 和 Gradle 版本进行调整。
- 操作系统:不限(macOS、Linux、Windows 均可)。
- IDE:强烈推荐IntelliJ IDEA(社区版或旗舰版),它对 Kotlin 和 Gradle 的支持最完善,也能最先体验到 Toolchain 的新特性。
- JDK:建议使用JDK 17 或 21(LTS 版本),这是 Kotlin 编译和现代 Java 生态的主流选择。
- 在 IDEA 中,可以通过
File -> Project Structure -> SDKs添加和配置 JDK。 - 这也是之前“jetbrains amper配置jdk位置”这个热词的来源——在 Amper 项目中,JDK 位置通常在 IDE 层面或项目级
settings.yaml中配置,比传统 Gradle 更隐蔽。
- 在 IDEA 中,可以通过
- Kotlin 版本:本文示例基于Kotlin 2.0.0或更高版本,因为许多简化构建的新特性在这个里程碑版本附近引入。
- Gradle 版本:建议使用Gradle 8.5或更高版本,并启用版本目录(Version Catalogs)等现代特性。
你可以通过以下命令检查版本:
./gradlew --version3. 核心变化:从 Amper YAML 到增强型 Gradle Kotlin DSL
Amper 的核心遗产是其声明式配置。我们来看看这些理念如何体现在未来的 Kotlin Gradle 构建中。
3.1 模块定义的简化
过去(传统 Gradle KMP 配置片段):
// build.gradle.kts (传统方式,冗长) kotlin { jvm() androidTarget { compilations.all { kotlinOptions { jvmTarget = "11" } } } iosX64() iosArm64() // ... 需要为每个平台重复配置 sourceSets { val commonMain by getting { dependencies { implementation(kotlin("stdlib-common")) implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.8.0") } } val jvmMain by getting { /* ... */ } // ... 需要为每个source set配置依赖 } }未来方向(更声明式的 Kotlin DSL): Kotlin Gradle 插件正在向更简洁的 API 发展。虽然完全达到 Amper YAML 的简洁度还需时日,但趋势是减少样板代码。例如,通过扩展函数和预设,平台声明可能变得更简单:
// build.gradle.kts (未来可能的简化风格) kotlin { // 目标:一行代码声明多个常用平台 multiplatformTargets(jvm, android, ios) // 注意:此为概念示例,非当前正式API sourceSets { commonMain.dependencies { implementation(libs.kotlinx.coroutines.core) // 使用版本目录 } // 插件可能自动创建对应的 jvmMain, androidMain, iosMain 等源集 } }当前,我们可以通过使用kotlin(“multiplatform”)插件和其提供的androidTarget、jvm等 DSL,已经比早期简化了很多。
3.2 依赖管理的进化:版本目录(Version Catalogs)
这是 Amper 理念影响下,当前就能立即采用的最佳实践。Amper 的module.yaml中依赖声明很简洁。Gradle 的版本目录功能提供了类似甚至更强大的管理能力。
1. 创建版本目录文件 (gradle/libs.versions.toml):
# gradle/libs.versions.toml [versions] kotlin = "2.0.0" coroutines = "1.8.0" koin-core = "3.6.0" [libraries] kotlin-stdlib = { module = "org.jetbrains.kotlin:kotlin-stdlib", version.ref = "kotlin" } kotlinx-coroutines-core = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-core", version.ref = "coroutines" } koin-core = { module = "io.insert-koin:koin-core", version.ref = "koin-core" } [bundles] common-deps = ["kotlinx-coroutines-core", "koin-core"]2. 在build.gradle.kts中使用:
kotlin { jvm() androidTarget() iosX64() sourceSets { val commonMain by getting { dependencies { // 使用版本目录中定义的库,清晰且一致 implementation(libs.kotlinx.coroutines.core) implementation(libs.koin.core) // 或者使用 bundle implementation(libs.bundles.common.deps) } } } }这种方式将依赖声明与版本号分离,集中管理,极大提升了大型项目的可维护性,与 Amper 的简洁理念不谋而合。
3.3 配置集中化与约定优于配置
Amper 强调通过module.yaml一个文件完成核心配置。在 Gradle 中,我们可以通过以下方式模拟:
- 使用
buildSrc或约定插件(Convention Plugins):将通用的配置(如 Android 配置、代码静态分析、发布设置)抽取到独立的插件中,使主build.gradle.kts文件保持清爽。 - 利用 Gradle 的
kotlin-dsl:编写类型安全的构建逻辑,享受 IDE 的自动补全和错误检查。
4. 完整实战:将一个“Amper风格”想法迁移到现代 Gradle KMP 项目
假设我们有一个简单的多平台库项目,其 Amper 理念是:一个清单文件定义库、平台和基础依赖。我们现在用现代 Gradle 实践来实现它。
4.1 创建项目结构
使用 IntelliJ IDEA 的“New Project”向导,选择“Kotlin Multiplatform”,模板选择“Library”即可。或者手动创建如下结构:
my-kmp-library/ ├── gradle/ │ └── libs.versions.toml # 版本目录 ├── build.gradle.kts # 根项目构建脚本 ├── settings.gradle.kts # 设置文件 ├── gradlew ├── gradlew.bat └── src/ ├── commonMain/kotlin/ # 通用代码 ├── commonTest/kotlin/ ├── jvmMain/kotlin/ # JVM平台代码 ├── androidMain/kotlin/ # Android平台代码 └── iosMain/kotlin/ # iOS平台代码 (根据目标细分)4.2 配置根项目构建脚本 (settings.gradle.kts)
启用插件解析和版本目录。
// settings.gradle.kts pluginManagement { repositories { mavenCentral() gradlePluginPortal() } } dependencyResolutionManagement { repositories { mavenCentral() } // 启用版本目录 versionCatalogs { create("libs") { from(files("gradle/libs.versions.toml")) } } } rootProject.name = "my-kmp-library"4.3 配置模块级构建脚本 (build.gradle.kts)
这是体现“Amper 简化精神”的核心。
// build.gradle.kts plugins { kotlin("multiplatform") version "2.0.0" // 如果你需要发布到 Maven,可以添加 `maven-publish` } // 类似于 Amper 的 `product` 和 `type` group = "com.example" version = "1.0-SNAPSHOT" kotlin { // 1. 声明目标平台 - 对应 Amper 的 `platforms` // JVM jvm { withJava() // 可选,生成JVM字节码的同时也支持Java工具链 } // Android androidTarget { compileSdk = 34 // 根据你的目标SDK设置 } // iOS (这里同时模拟了Amper的 `iosArm64`) iosArm64() iosSimulatorArm64() // 为 Apple Silicon 模拟器添加 // 2. 配置源集和依赖 - 对应 Amper 的 `dependencies` sourceSets { val commonMain by getting { dependencies { // 使用版本目录,清晰简洁 implementation(libs.kotlinx.coroutines.core) // Kotlin标准库由插件自动添加 } } val commonTest by getting { dependencies { implementation(kotlin("test")) // 通用测试库 } } // JVM特定源集和依赖会自动继承commonMain,也可单独配置 val jvmMain by getting { dependencies { // JVM平台特定依赖 // implementation(libs.some.jvm.lib) } } // Android特定源集 val androidMain by getting { dependencies { // Android平台特定依赖 // implementation(libs.androidx.core) } } } }4.4 配置 Android 特定选项
如果需要 Android 配置,可以添加 Android Gradle Plugin 并配置。
// 在 plugins 块添加 // plugins { // ... // id("com.android.library") version "8.4.0" apply false // 根项目 // } // 在 androidTarget 配置块后,可以配置 android 扩展(如果应用了 android 插件) // android { // namespace = "com.example.mylibrary" // compileSdk = 34 // defaultConfig { // minSdk = 24 // } // }注意:在多平台项目中配置 Android 需要更细致的设置,上述仅为示意。通常建议使用androidTarget的 DSL 进行配置。
4.5 运行与验证
- 同步项目:在 IDEA 中,打开
build.gradle.kts文件,右上角会提示“Load Gradle Changes”或“Sync”,点击它。 - 编写代码:在
src/commonMain/kotlin下创建一个文件,例如Greeting.kt:package com.example.library class Greeting { fun greet(): String { return "Hello from Kotlin Multiplatform!" } } - 执行测试:在 IDEA 中,找到
src/commonTest/kotlin下的测试文件,或运行 Gradle 任务:./gradlew allTests # 或针对特定目标 ./gradlew jvmTest ./gradlew iosSimulatorArm64Test - 构建所有目标:
./gradlew assemble
如果一切顺利,你将在build/libs和build/binaries等目录下找到生成的 JAR 包(JVM)、AAR 包(Android)和 Framework(iOS)。
5. 常见问题与排查思路
在从 Amper 概念或传统复杂配置转向现代 Gradle KMP 时,你可能会遇到以下问题。
| 问题现象 | 常见原因 | 解决思路 |
|---|---|---|
同步失败:Unresolved reference: libs | 1.settings.gradle.kts中未正确启用versionCatalogs。2. libs.versions.toml文件路径或格式错误。 | 1. 检查settings.gradle.kts的dependencyResolutionManagement块。2. 确保 libs.versions.toml文件在gradle/目录下,且 TOML 语法正确(无中文符号)。 |
编译错误:expect/actual声明不匹配 | 1. 在commonMain中声明了expect,但在某个平台(如jsMain)的源集中没有提供对应的actual实现。2. 平台源集目录未正确创建。 | 1. 确保所有声明的expect在需要的平台源集中都有actual实现。2. 在 IDEA 中,右键点击 kotlin目录,选择New->Kotlin Class/File,并确保路径正确(如jvmMain/kotlin)。 |
| iOS 构建失败:找不到签名或模拟器 | 1. 在非 macOS 上尝试构建 iOS 目标。 2. macOS 上 Xcode 或命令行工具未安装或未配置。 3. 没有可用的 iOS 模拟器或真机设备。 | 1. iOS 目标(iosArm64,iosX64等)只能在 macOS 上构建。2. 确保已安装 Xcode 及命令行工具 ( xcode-select --install)。3. 打开 Xcode 确保有可用的模拟器,或连接真机。对于纯库开发,可考虑使用 iosSimulatorArm64仅构建模拟器目标。 |
| 依赖下载慢或失败 | 1. 网络问题。 2. Maven 仓库地址配置问题。 | 1. 检查网络连接,或配置国内镜像(如阿里云 Maven 仓库)。 2. 在 settings.gradle.kts的repositories块和build.gradle.kts的repositories块中添加镜像。 |
| Android 构建配置错误 | 1.androidTarget配置中compileSdk等版本与本地 SDK 不匹配。2. 未正确应用 Android Gradle Plugin (AGP)。 | 1. 使用 Android Studio 的 SDK Manager 安装指定版本的compileSdk。2. 确保 AGP 版本与 Gradle 版本兼容。查阅官方兼容性表格。 |
| “Toolchain” 相关 JDK 错误 | 1. 项目指定的 Kotlin 编译器版本与当前 JDK 不兼容。 2. IDEA 中项目 SDK 设置错误。 | 1. 确保使用 JDK 11 或更高版本(推荐 17/21)。 2. 在 IDEA 中,检查 File -> Project Structure -> Project下的SDK和Project language level。在File -> Project Structure -> SDKs中添加正确的 JDK。 |
6. 最佳实践与工程建议
拥抱 Kotlin Toolchain 的进化,不仅仅是修改配置语法,更是采纳一套更高效的工程实践。
6.1 构建配置管理
- 优先使用版本目录 (
libs.versions.toml):这是管理依赖版本和避免冲突的首要推荐方案。它为整个项目提供单一事实来源。 - 开发约定插件:对于大型项目或多模块项目,将通用的编译选项、代码质量检查(Detekt、Ktlint)、测试配置等封装到
buildSrc或预编译的约定插件中。这能使每个子模块的build.gradle.kts极其简洁,只需apply插件即可。 - 保持 Gradle 包装器(Gradle Wrapper)更新:使用
./gradlew命令,确保团队所有成员使用完全相同的 Gradle 版本,避免环境差异问题。
6.2 多平台代码组织
- 最大化共用代码:严格遵守 KMP 的
expect/actual机制。将平台无关的逻辑尽可能放在commonMain中。平台相关 API(如文件 IO、网络、UI)才使用expect声明,并在各平台实现。 - 善用源集依赖:除了
commonMain,你还可以创建commonAndroidMain这样的中间源集,供androidMain和jvmMain共享,但iosMain不共享。 - 模块化拆分:当共用逻辑变得庞大复杂时,考虑将其拆分为多个独立的 Kotlin 多平台模块,通过
api或implementation依赖进行组合。
6.3 依赖与发布
- 注意依赖范围:在
commonMain中只能添加多平台库或expect对应的actual实现库。平台特定依赖必须添加到对应的平台源集(如jvmMain,androidMain)中。 - 发布到 Maven 仓库:使用
maven-publish插件,并正确配置kotlin(“multiplatform”)插件提供的publishing扩展,确保发布的 POM 文件包含正确的依赖和作用域(metadata,jvm,android,ios等变体)。 - 版本号管理:遵循语义化版本控制(SemVer)。对于快照版本(
-SNAPSHOT)和正式版本,使用不同的仓库。
6.4 持续集成与测试
- 为所有目标平台运行测试:在 CI 流水线中,不仅要运行
commonTest,还要运行jvmTest、androidUnitTest等。对于 iOS,可以在 macOS CI 节点上运行模拟器测试。 - 缓存 Gradle 和 Kotlin/Native 编译输出:Kotlin/Native 编译(尤其是 iOS)比较耗时。在 CI 中配置好缓存(如 Gradle 的
~/.gradle/caches, Kotlin/Native 的~/.konan),可以大幅提升构建速度。 - 使用构建缓存(Build Cache):启用 Gradle 的本地或远程构建缓存,加速增量构建。
6.5 关注 Kotlin 生态演进
- 留意 Kotlin 版本更新日志:每个 Kotlin 版本都可能带来构建 DSL 的改进、新平台目标的实验性支持或性能优化。例如,Kotlin 2.0 在编译器性能和 K2 上带来了巨大变化。
- 关注 Kotlin 官方博客和 YouTrack:关于构建工具链(Toolchain)的进一步整合消息,JetBrains 会通过官方渠道发布。例如,未来可能出现的更简洁的“模块定义”DSL。
- 参与社区:Kotlin Slack、Reddit 的 r/Kotlin 或相关中文论坛是获取最新实践和解决疑难杂症的好地方。
Amper 的探索并非徒劳,它像一颗投入湖面的石子,激起的涟漪正在推动整个 Kotlin Toolchain 生态向着更简单、更统一的方向演进。对于我们开发者而言,无需为 Amper 的“离去”感到惋惜,更不必急于寻找替代品。正确的做法是:拥抱并深入掌握主流的 Gradle for Kotlin Multiplatform,同时积极采纳版本目录、约定插件等现代最佳实践。
这些实践正是 Amper 思想精华的体现。通过本文的梳理和实战,你应该已经能够搭建一个结构清晰、配置现代、易于维护的 Kotlin 多平台项目。记住,工具的本质是提升效率,减少心智负担。将你的精力更多地投入到创造性的业务逻辑和跨平台代码共享上,这才是 Kotlin Multiplatform 和其不断进化的 Toolchain 带给我们的最大价值。