Slackbot
07/31/2022, 10:49 PMVampire
07/31/2022, 10:59 PMEli Graber
07/31/2022, 11:21 PMVampire
07/31/2022, 11:22 PMEli Graber
07/31/2022, 11:50 PMfun Project.configureKgp(
optIns: List<String>
) {
plugins.withType(KotlinBasePluginWrapper::class.java) {
with(extensions.getByType(KotlinProjectExtension::class.java)) {
sourceSets.configureEach {
for(optIn in optIns) languageSettings.optIn(optIn)
}
}
}
}
I have another library (plugins) that has a precompiled script plugin which calls configureKgp
and uses an extension to get a default (emptyList
) or user provided value for optIns
.
The plugins library will be used across many different apps and libraries, each of which have many projects.
In general they will be fine with the plugins defined default value of emptyList
, but there are some apps where every project needs to have optIns
default to listOf("kotlin.js.ExperimentalJsExport")
.
I don't want to have to specify that in each project, so I'd like to have a way to configure a default value for it in the app's build.gradle.kts
The options that I'm aware of are:
1. Use subprojects
, but my understanding is that this is considered an anti pattern, and will not work with the upcoming project isolation
2. Use buildSrc
or an included build, but the whole point of the plugins library is to try and avoid that
3. Use gradle.properties
, but that seems too loose
So what I'm hoping for is some kind of object that lives in the plugins library that has default values which is used to set the default on the extension, but I can override those default values in the root project.
However, in order for that to work, I would need to rely on the root project being configured before any children.Vampire
08/01/2022, 9:45 AMEli Graber
08/09/2022, 7:05 PMabstract class MyDefaults : BuildService<BuildServiceParameters.None> {
abstract val optIns: SetProperty<String>
}
abstract class MyDefaultsPlugin : Plugin<Project> {
override fun apply(target: Project) {
require(target == target.rootProject)
val ext = target.extensions.create<MyExtension>("myExtensionDefaults")
val service = target.gradle.sharedServices.registerIfAbsent("myDefaults", MyDefaults::class) {}
ext.awaitKotlinConfiguration { kotlin ->
service.get().optIns.set(kotlin.optIns)
}
}
}
Then in the consumer root project I apply the plugin and configure the extension:
myExtensionDefaults {
kotlin.optIns = setOf("...")
}
Then in a consumer subproject I get the service, and configure subproject's extension with the service values before it gets configured:
val service = gradle.sharedServices.registrations.findByName("myDefaults")!!.service.get() as MyDefaults // is there a better way to do this
myExtension.kotlin.optIns = service.optIns.get()
myExtension.awaitKotlinConfiguration { kotlin ->
// kotlin.optIns has the value from the service, unless the user set it in the extension in the subproject
// configure kgp with kotlin.optIns
}
Vampire
08/09/2022, 7:32 PMEli Graber
08/09/2022, 7:36 PMVampire
08/09/2022, 8:43 PMregisterIfAbsent
, as you rely on it being registered already, it should work fine to give the existing one