samuel
04/23/2023, 11:10 PMExtensionContainer
while creating a custom gradle plugin on android. In order to create an extension at the project scope i do this:
project.extensions.create(
"myExtension",
MyExtension::class.java
)
Is there a way i can create an extension that is scoped to applicationVariants so i can configure the variants like this:
android.applicationVariants.configureEach { variant ->
myOtherExtension {
// configuration
}
}
Vampire
04/23/2023, 11:45 PMExtensionAware
though if it does not decalare it.samuel
04/23/2023, 11:52 PMconfigure<MyExtensionClass>{
// configuration
}
I was hoping I could get it more ergonomically directly as
myOtherExtension {
// configuration
}
Vampire
04/23/2023, 11:57 PMsamuel
04/24/2023, 12:02 AMAdam S
04/24/2023, 7:54 AMandroid.applicationVariants
is a NamedDomainObjectContainer<T>
, and you’re adding extensions to every T
.
android.applicationVariants.configureEach { variant ->
// all types that Gradle instantiate are ExtensionAware, but you might need to manually cast to tell the Kotlin compiler
//require(variant is ExtensionAware)
variant.extensions.create(
"myExtension",
MyExtension::class.java
)
}
And then in code you can configure the extensions
android.applicationVariants.configureEach { variant ->
variant.configure<MyExtension> { // retrieve and configure MyExtension, failing if it doesn't exist
// configuration
}
}
However, just because every T
has the same extension, that doesn’t mean Gradle will generate a generic DSL accessor!
So Gradle might* generate a DSL accessor for every specific element (*as I said, it’s tricky, there are some caveats I’m not explaining right now), but that doesn’t mean it will generate an accessor that you can use like this:
// build.gradle.kts
android.applicationVariants.configureEach {
myExtension {
// configuration
}
}
Of course in Groovy you can do that, because Groovy lets you do anything (even if it’s wrong).
To work around it you could define your own Kotlin DSL function.
fun ApplicationVariant.myExtension(configure: MyExtension.() -> Unit) {
variant.configure<MyExtension>(configure)
}
If you wanted to be clever/risky/sneaky you could even put that function in an implicitly imported package, so it would be available automatically to users
@file:Suppress("PackageDirectoryMismatch")
package org.gradle.kotlin.dsl
fun ApplicationVariant.myExtension(configure: MyExtension.() -> Unit) {
configure<MyExtension>(configure)
}
samuel
04/24/2023, 8:13 AMAdam S
04/24/2023, 8:22 AM