自定义Gradle插件报错:LibraryExtension不存在问题求助
问题场景
开发了一个Gradle插件用于统一配置项目各模块,构建时触发如下报错:
org.gradle.api.plugins.InvalidPluginException: An exception occurred applying plugin request [id: 'common.plugin']
Caused by: org.gradle.api.UnknownDomainObjectException: Extension of type 'LibraryExtension' does not exist. Currently registered extension types: [ExtraPropertiesExtension,....]
项目采用build-logic convention插件架构,包含多个Android模块(应用模块+库模块),意图通过自定义插件统一管理配置。
插件核心代码(CommonPluginClass)
class CommonPluginClass : Plugin<Project> { private val consumerProguardFileName = "consumer-rules.pro" private val proguardFileName = "proguard-rules.pro" private val sdkToCompile = 33 override fun apply(project: Project) { println(">>>> Adding sugar to gradle files!") with(project) { applyPlugins(this) androidConfig(this) } println(">>>> Sugar added for core Module!") } private fun applyPlugins(project: Project) { println(">>>> apply plugins!") project.pluginManager.run { apply("com.android.application") apply("kotlin-android") apply("kotlin-kapt") } println(">>>> end apply plugins!") } private fun androidConfig(project: Project) { project.extensions.configure<LibraryExtension>{ defaultConfig.targetSdk = 33 } } }
报错发生在androidConfig函数调用configure<LibraryExtension>时。
build-logic:convention的build.gradle配置
plugins { alias(libs.plugins.kotlin.jvm) apply false id "org.gradle.kotlin.kotlin-dsl" version "2.4.1" } dependencies { compileOnly(libs.android.pluginGradle) compileOnly(libs.kotlin.pluginGradle) } gradlePlugin { plugins { commonPlugin { id = "common.plugin" implementationClass = "CommonPluginClass" } } }
补充更新
排查发现所有模块均被识别为ApplicationExtension,需解决该构建问题。
解决方案
1. 区分模块类型,动态应用Android插件
当前代码强制给所有模块应用com.android.application插件,导致库模块也被标记为应用模块,因此无法找到LibraryExtension。需根据模块类型动态选择插件:
private fun applyPlugins(project: Project) { println(">>>> apply plugins!") project.pluginManager.apply("kotlin-android") project.pluginManager.apply("kotlin-kapt") // 可通过模块名称约定、Manifest内容判断模块类型 val isAppModule = project.name == "app" // 或通过Manifest判断:project.file("src/main/AndroidManifest.xml").readText().contains("android:name=\".MainActivity\"") if (isAppModule) { project.pluginManager.apply("com.android.application") } else { project.pluginManager.apply("com.android.library") } println(">>>> end apply plugins!") }
2. 适配不同Extension类型配置
配置Android参数时,根据当前模块的Extension类型选择对应处理逻辑:
import com.android.build.api.dsl.ApplicationExtension import com.android.build.api.dsl.LibraryExtension private fun androidConfig(project: Project) { project.extensions.findByName("android")?.let { extension -> when (extension) { is ApplicationExtension -> { extension.defaultConfig.targetSdk = 33 // 应用模块专属配置,如applicationId等 } is LibraryExtension -> { extension.defaultConfig.targetSdk = 33 extension.consumerProguardFiles(consumerProguardFileName) // 库模块专属配置 } } } }
3. 参考NowInAndroid约定式拆分插件
NowInAndroid采用拆分插件的方式分别处理应用/库模块,可参考该模式:
- 新建
AndroidAppConventionPlugin专注处理应用模块配置 - 新建
AndroidLibraryConventionPlugin专注处理库模块配置 - 项目模块根据自身类型,对应应用上述插件
内容的提问来源于stack exchange,提问作者Thorny84

