Is there any way inside build.gradle.kts to define...
# community-support
н
Is there any way inside build.gradle.kts to define some variable that will be accessible right away by plugins applied in
plugins {}
block.
m
The
plugins {}
block is special and evaluated before the rest of the script.
If you want to share a version, I'd recommend using version catalogs
н
Basically I want my plugin to behave differently depending on what I set as let’s say
type
variable in the project build script itself. I can’t react to this
type
variable in afterEvaluate in plugin as it’s too late for my purposes. And whatever properties I set through extensions are evaluated after plugin was already applied.
m
My goto solution for this is to move the logic from
Plugin::apply
to
MyExtension::foo
Your plugin registers the "myExtension" extension and then the user of the plugin can control the behaviour
Copy code
plugins {
  id("my.plugin")
}

// You can use regular Kotlin here
val type = "someType"
myExtension {
  // foo is a function so you can execute code inside and pass parameters
  foo(type)
}
н
Yeah it would work if I only have one plugin that needs this variable. But the issue is that I have several convention plugins do configuration on top of each other. Maybe I can make extension as holder of some Action<T>. Each plugin will register a configuration action in the extension. And all actions will be executed on execution of foo(type)
m
If your variable is only used at execution time, you can move it to a
Provider<T>
and refer it from all your plugins
☝️ 1
But if you need it to build the task graph, there's no silver bullet. You'll have to use function calls
н
Basically I’m making white-label system for project with multiple apps, each white-label app has a slightly different configuration. My first draft was to have white-label extension that has
Copy code
WhiteLabelExt {
   type: Property<Type>
}
And each plugin applies it’s part of setup depending on this type. But the issue is that actual value is set after I applied plugins. So plugins have no value to work with. I can’t delay configuration that plugin applies to something like afterEvaluate stage, and I haven’t figured out how I can setup some kind of observer pattern on my
type
property to execute configuration action as soon as property is set.
e
Copy code
WhiteLabelExt {
    setType(Type)
}
would be observable as soon as it's called
👆 2
н
Not sure what do you mean by observable? I need to trigger some action that will be set up in plugin that will be executed as soon as Property<Type> gets it actual value. Basically observer pattern with callbacks
e
you can't observe a Property but you can observe a function call (or a property setter, that isn't a Property). and both Property and property can be set with the same
Copy code
whiteLabelExt {
    type = Type.FOO
}
syntax in consumers, so it might be a simple change to make (not binary compatible of course)
l
Just to chime in here, @Martin is correct, you should use extensions for this (it provides a user-configurable block for your plugin). Extensions should use Configuration Cache-friendly types. So again, as @Martin mentioned, use Providers and the Provider API.
I need to trigger some action that will be set up in plugin that will be executed as soon as Property<Type> gets it actual value. Basically observer pattern with callbacks
Would a custom task in your plugin work for this?
Copy code
tasks.named("configureWhiteLabel") {
    // runs after type is set
}
н
Would a custom task in your plugin work for this?
Tasks will not help me as I need to configure the project during the configuration phase.
l
Would any of the lifecycle callbacks be useful? https://docs.gradle.org/release-nightly/userguide/build_lifecycle.html#lifecycle_api I know you mentioned
afterEvaluate
but there are others.
m
@Николай Клебан Why do you need that logic to happen during configuration phase?
н
Would any of the lifecycle callbacks be useful?
I don’t think so, callbacks like beforeProject seems like should be executed in settings and I really want to keep my configuration in the module build.gradle.kts
Why do you need that logic to happen during configuration phase?
Basically I’m doing Android related configuration, adding flavors, and doing some work with tasks based on formed variants in AndroidComponentsExtension.onVariants
m
I see. Yea adding variants need to happen at configuration time. Then a function in your extension is how I would do it. That function may react on AGP with
pluginManager.withId
👆 1