https://kotlinlang.org logo
#gradle
Title
# gradle
r

Raphael

09/21/2023, 3:25 PM
I have created a plugin for doing all the configuration of our android builds. Now the request came from some devs that they would like to have a config file in the root to configure a default for all the project. The structure looks the following:
Copy code
/
/gradlePlugins <-- In here plugins are specified
/subProjectA
/subProjectB
/build.gradle.kts <-- should apply the plugin to all subprojects and should apply the default config
/settings.gradle.kts <-- here the plugin is included
/default-config.gradle.kts
The defualt-config.gradle.kts should look something like this:
Copy code
apply(plugin = "my-plugin")

myPluginConfig {
  foo="bar"
}
The build.gradle.kts should include this config something like this:
Copy code
...
subprojects {
  apply(from = "default-config.gradle.kts")
}
Unfortunately this doesn't work. 1. Because i cannot apply the plugin in the
subprojects
container due to
Cannot run Project.afterEvaluate(Action) when the project is already evaluated.
2. The
default-config.gradle.kts
cannot resolve
myPluginConfig
as well as any imports of it. I have tried countless different scenarios without any luck. Does anyone have an idea on how to do that?
j

Justin Tullgren

09/21/2023, 3:59 PM
I would recommend moving to a compiled plugin with a configurable extension that has the sensible defaults.
Copy code
/
/buildLogic
/buildLogic/settings.gradle.kts
/buildLogic/build.gradle.ks
/project
/project/settings.gradle.kts
/project/build.gradle.kts
/project/module
/project/module/build.gradle.kts
/project/settings.gradle.kts
Copy code
pluginManagement {
  includeBuild("buildLogic")
}
/project/build.gradle.kts
Copy code
plugins {
id("my.custom.plugin") apply false
}
r

Raphael

09/21/2023, 4:01 PM
This is how it is currently set up. The request I got is that the extension should be easily configurable with defaults in the root of the project. The part of the root is what makes it complicated.
j

Justin Tullgren

09/21/2023, 4:03 PM
Then I would look into convention plugins, where you define your plugin with all the default stuff and each project can override as they choose
settings.gradle.kts is separate from the the build. There are settings plugins but thats not for build logic but gradle configuration
Copy code
class MySettings : Plugin<Settings>
You could also make all of your defaults read from
gradle.properties
if you wanted to
https://github.com/android/nowinandroid is a good resource to see how they use conventions in a build plguin
also, it is recommended to move away from
apply(plugin = "my-plugin")
and to instead use the
plugins
dsl
r

Raphael

09/21/2023, 4:51 PM
Thank you, I will look into it tomorrow.
v

Vampire

09/21/2023, 8:58 PM
Just to have another voice:
Copy code
/build.gradle.kts <-- should apply the plugin to all subprojects and should apply the default config
Given you mean using
allprojects { ... }
or
subprojects { ... }
, definitely not. Both are highly discouraged and should not be used as they immediately introduce project coupling which disturbs more sophisticated Gradle features, and makes Gradle builds much harder to understand and much harder to maintain. As Justin said, use (or stay with) convention plugins. If you got a request to change from convention plugins to
subprojects { ... }
, just answer with "no, not without a time-machine going back to stone age". 🙂
The defualt-config.gradle.kts should look something like this
Definitely not. Such legacy script plugins (the ones applied with "apply from" are bad practice and have many bad details and class loader traps that you really want to avoid. Besides that you also do not get type-safe accessors like
myPluginConfig { ... }
in them unless you manually provide them. Overall, you should just not do it.
Cannot run Project.afterEvaluate
You should avoid
afterEvaluate
as hell anyway. In 98.7 % of the cases it is the wrong thing to do. It is typically just symptom treatment and shifting the problem to a later much harder to reproduce, debug, and fix time. The main thing using
afterEvaluate
causes are ordering and timing problems and race conditions.
7 Views