必须用 org.jetbrains.kotlin.multiplatform 当且仅当目标平台包含 jvm 以外的 android/ios/js/native 中任一;它本质是协调多编译器的构建拓扑约束,与 kotlin.jvm 插件完全不兼容。

只面向 JVM(比如纯后端服务、Java/Kotlin 工具库),就用 org.jetbrains.kotlin.jvm;只要涉及 Android + iOS / JS / Native 中任一其他平台,就必须用 org.jetbrains.kotlin.multiplatform。
什么时候必须用 org.jetbrains.kotlin.multiplatform
不是“想复用代码才选”,而是“目标平台不止 JVM”就绕不开它。KMP 插件本质是多编译器协调器:它要同时调度 Kotlin/JVM、Kotlin/Native、Kotlin/JS 编译器,并管理 commonMain、androidMain、iosMain 等 source set 之间的依赖和符号导出规则。
- 哪怕你当前只写了
commonMain和androidMain,只要build.gradle.kts里声明了iosX64()或js()目标(哪怕没写代码),就必须用 KMP 插件 - Android Studio 的 KMP 模板、JetBrains 官方脚手架生成的项目,默认都用 KMP 插件——因为它们预设支持多平台扩展
- 用
org.jetbrains.kotlin.jvm强行加iosArm64会直接报错:Cannot add target 'iosArm64': unsupported by current plugin
为什么不能混用或“先用 JVM 再升级”
KMP 插件和 JVM 插件的 Gradle 扩展模型完全不同。前者暴露的是 KotlinMultiplatformExtension,后者是 KotlinJvmProjectExtension;它们注册的 task、source set 生命周期、编译参数注入点全部不兼容。
- 在同一个模块里同时 apply 两个插件,Gradle 会抛出
Extension with name 'kotlin' already exists - 试图在 JVM 插件基础上手动添加
targets.withType(KotlinTarget::class)—— 这个 API 根本不存在,KMP 插件才提供targets容器 - Android Gradle Plugin 9.0+ 已弃用旧式
com.android.library配合 KMP 的 hack 方式;现在官方唯一推荐路径就是com.android.kotlin.multiplatform.library插件 +org.jetbrains.kotlin.multiplatform
org.jetbrains.kotlin.jvm 的典型误用场景
开发者常因“暂时只跑在 Android 上”而选错,但 Android ≠ JVM。Android 使用的是 ART/Dalvik 运行时,字节码格式与 JVM 不完全一致,且 KMP 的 androidTarget 会自动处理 ABI 分割、Proguard 规则注入、AGP 协作等细节。
- 你写了个
data class User放在commonMain,想在 Android 模块里直接用——这必须走 KMP 插件,否则androidMain根本看不到commonMain的符号 - 用
org.jetbrains.kotlin.jvm编译出的 jar 包,无法被 iOS 模块通过 CocoaPods 或 SPM 正确链接;KMP 插件生成的.framework或.klib才含正确的 Objective-C/Swift header 和符号表 - 即使只部署到 Android,若未来要加 iOS,用 JVM 插件的项目需重写整个 build 脚本、迁移 source set 结构、重新配置依赖——远比一开始用 KMP 插件成本高
真正容易被忽略的点是:KMP 插件不是“功能开关”,而是构建拓扑的底层约束。一旦项目结构里出现 iosMain 或 jsMain 目录,或者 build 脚本里调用了 targets、sourceSets、compilations 等 KMP 特有 DSL,你就已经站在 KMP 插件的契约上了——换插件不是改一行代码的事,是重构整个构建语义。











