This message was deleted.
# community-support
s
This message was deleted.
👀 1
v
It should be the case currently afair. But I'm not sure you should really rely on that. What is your use-case?
e
I want to configure an object that will be used to set defaults in child projects.
v
Your description is still a bit vague, maybe a shared build service is what your want?
e
I think that's a little overkill for what I need. I'll try to describe it better. I have a library (utils) with the following function:
Copy code
fun 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.
v
Maybe it would be safer to configure these defaults in the settings script. Settings script is definitely evaluated before any build script and is probably the more appropriate place for build-wide settings.
e
I ran into some issues with configuring project wide defaults with a settings plugin (related to classpath problems that would require me to refactor my project to see if it would work), so I'm trying out using a shared build service. Should I anticipate any issues using it this way? The root project configuration (and thus the service properties getting set) seems to be happening before any subprojects get configured. I define a plugin meant for the root project and service in a library:
Copy code
abstract 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:
Copy code
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:
Copy code
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
}
v
Sharing data between projects using a shared build service is fine. Also setting something at configuration time to read it at configuration time should be fine. Depending on root project being evaluated first I'm not too sure. Afair currently it is always evaluated first, yes, but I don't think it is guaranteed somewhere and I have no idea whether this might eventually change at some time.
e
I figured I'll rely on that for now, and if it ever changes I'll refector to use settings. Is there a better way to get a reference to the service in the subproject
v
Afair just
registerIfAbsent
, as you rely on it being registered already, it should work fine to give the existing one
👍 1