Is there a good way to access constants defined in...
# plugin-development
m
Is there a good way to access constants defined in the included build, in the outer project buildscripts? I have started moving our multimodule Android project towards convention plugins. Before, all the configuration was done on the root project level via ext properties. So say we had
ext.compileSdk = 23
then subprojects could access it via
rootProject.ext.compileSdk
. Now moved the common plugin configurations to convention plugins in an included build. Say in the included build I have now
Copy code
object Constants {
  val compileSdk = 23
}
I use this value in the convention plugins, but for legacy reasons this value is also needed in some other buildscript in the project. I don't want to have it duplicated just for that. I think I am able to read that value directly in
*.kts
files but not in
.gradle
files. (Why?) I have figured out I can create some kind of ConstantsConventionPlugin
Copy code
class ConstantsConventionPlugin : Plugin<Project> {

    override fun apply(project: Project) {
        project.extensions.extraProperties.set("ANDROID_COMPILE_SDK", Constants.compileSdk)
    }
}
Can this be avoided? Is there a better alternative?
e
if it's a binary plugin, you are able to reference
Constants.compileSdk
in build scripts just like you would any other code
m
Will it work in groovy dsl though?
e
yes
well, Groovy has certain interoperability issues with Kotlin so you may end up needing
Constants.$INSTANCE.compileSdk
but basically the same thing
m
Oh Good Lord, it works indeed, Thanks! And without $INSTANCE even
Ah, I got it now. The reason why I thought it works in
*.kts
but not in
*.gradle
is that in every *.kts where I needed it, it already had one of the plugins from the included module applied. However I had none applied in the *.gradle file where I tried. Which means I can make a dummy, marker plugin that does nothing just to get my
Constants
on the classpath.
e
yes. you could also
plugins { id('...') apply false }
to just get it into the buildscript classpath
v
Actually, I'd recommend moving versions to a version catalog defined as TOML file instead. That will also be much better when you change a version, because if you now change that sdk version, each and every task that is not built-into Gradle will be out-of-date. With a version catalog only the things actually using that version will be out-of-date.
And what I learned from Gradle folks is, everytime you use
ext
/
extra
properties you should feel dirty. They are practically always just a work-around for not doing something properly. 🙂
❤️ 1
1
So for example if you would have followed the road of a constants convention plugin, that plugin should have added an extension that has the constants which you then can access type-safely properly.
👍 1
e
version catalogs require a bit of ceremony for sharing between included builds, and in this case compileSdk is an
int
while version catalogs give you strings, but in general yes
several android constants don't need to be configured in convention plugins though, there is a settings plugin that will set defaults https://developer.android.com/build/releases/past-releases/agp-8-0-0-release-notes#settings-plugin (it works in kotlin now)
m
Following on this topic. Given that I have now a bunch of convention plugins, I would like to ensure people won't use bare plugins when creating new modules. My idea was to create a settings plugin that goes through evaluated projects checks the applied plugins, and say if there is bare android plugin ensures there is also convention plugin applied. (Not ideal, perhaps would be better to check what is actually applied in the plugins section of the checked project rather than what is the actual result of all the applied plugins). Still I ended with a bunch of duplications that I am not sure how to avoid. In the included build where I keep the convention plugins, the
build.gradle.kts
defines the plugin ids and the corresponding classes implementing those. However in the setting plugin I need to repeat those plugin ids. Ideally would be good to have possibility to enforce it on some interface level. Say every convention plugin would have to implement certain check to be applied as settings plugin. But at least I would like to be able to reference those plugin ids both in the settings plugin and in the convention plugins buildscript.