将KMM项目加入Android Gradle多项目构建时遇插件错误
项目背景
我有两个项目:一个供其他项目依赖的Android库项目,以及一个存储Android和iOS共用代码的Kotlin Multiplatform Mobile(KMM)项目。由于现有项目规模庞大,无法合并为单一KMM项目,因此希望将KMM的shared模块纳入Android库的构建流程,避免每次修改shared代码后都要发布到Maven Local才能在库项目及依赖它的项目中使用。
项目目录结构
AndroidLibrary <--- Android库主项目 |- kmmLibrary <--- KMM项目 |- shared |- build.gradle.kts |- build.gradle.kts |- settings.gradle.kts |- lib <---- Android库模块 |- build.gradle.kts |- build.gradle.kts |- settings.gradle.kts
尝试操作与报错
我尝试在AndroidLibrary/settings.gradle.kts中添加include ':kmmLibrary:shared',将shared模块纳入多项目构建,但同步Gradle或执行./gradlew时出现以下错误:
Build file '/pathtotheproject/AndroidLibrary/kmmLibrary/build.gradle.kts' line: 1 Error resolving plugin [id: 'org.jetbrains.kotlin.multiplatform', version: '1.8.21', apply: false] > The request for this plugin could not be satisfied because the plugin is already on the classpath with an unknown version, so compatibility cannot be checked.
单独构建KMM项目可以正常完成,只有在构建AndroidLibrary主项目时才会触发该错误。
相关配置代码
AndroidLibrary/kmmLibrary/build.gradle.kts
plugins { // 统一所有子模块的插件版本 id("com.android.library").version("8.0.2").apply(false) kotlin("multiplatform").version("1.8.21").apply(false) } ...
AndroidLibrary/kmmLibrary/shared/build.gradle.kts
plugins { kotlin("multiplatform") id("com.android.library") } ...
当前情况与需求
我已经通过Gradle复合构建(使用includeBuild 'kmmLibrary:shared')实现了基础功能,但希望改用多项目构建。因为复合构建无法通过api project(":kmmLibrary:shared")将shared模块的代码打包进AndroidLibrary的构建产物,导致依赖该库的第三方项目需要单独获取KMM模块的产物,而我希望只发布AndroidLibrary这一个产物,就能让所有依赖项目获取到更新。
解决方案
1. 移除KMM项目自身的settings.gradle.kts
将KMM的shared模块纳入AndroidLibrary的多项目构建后,KMM项目自身的settings文件会和主项目的配置冲突,导致插件版本解析混乱。直接删除AndroidLibrary/kmmLibrary/settings.gradle.kts。
2. 调整主项目settings.gradle.kts的配置
在主项目的settings文件中统一管理插件版本,并正确关联shared模块的路径:
pluginManagement { repositories { google() mavenCentral() gradlePluginPortal() } plugins { // 统一声明所有插件版本,覆盖KMM项目中的局部声明 id("com.android.library") version "8.0.2" kotlin("multiplatform") version "1.8.21" } } include(":lib") include(":kmmLibrary:shared") // 指定shared模块的实际目录路径 project(":kmmLibrary:shared").projectDir = file("./kmmLibrary/shared")
3. 修改KMM项目根build.gradle.kts
删除其中的插件版本声明,改用主项目统一管理的版本:
plugins { id("com.android.library").apply(false) kotlin("multiplatform").apply(false) } // 保留仓库等必要全局配置 allprojects { repositories { google() mavenCentral() } } ...
4. 在Android库模块中依赖shared模块
在AndroidLibrary/lib/build.gradle.kts中添加依赖,确保shared模块代码被打包进最终产物:
dependencies { api(project(":kmmLibrary:shared")) // 其他原有依赖 }
原理说明
错误的核心是多项目构建中存在两套插件版本声明:主项目和KMM子项目各自声明插件版本,导致Gradle无法确定版本优先级,抛出兼容性检查错误。通过在主项目的pluginManagement中统一管理所有插件版本,并移除KMM项目自身的settings文件,可让Gradle使用统一的插件版本解决冲突,同时实现shared模块代码被打包进AndroidLibrary产物的需求。
内容的提问来源于stack exchange,提问作者Piotr Śmietana

