I was just reading about applying a plugin from an...
# gradle
e
I was just reading about applying a plugin from another plugin (e.g., a convention plugin), sort of a pre-requisite. Seems it is indeed possible, but is it a good approach to take?
a
It depends! Sometimes it's fine to apply a plugin that's really common, like plugins that are packaged with Gradle. A lot of plugins will require BasePlugin because it provides common lifecycle tasks. Sometimes you want your plugin to be really opinionated, because it really requires a specific plugin is applied, which is most convention plugins. This tightly couples the plugins, which might be advantageous (e.g. for convention plugins, which are usually want to make sure an exact set of plugins are present), or disadvantageous because the consuming project can't 'opt out' of the plugin. Sometimes it's best to react to plugins, so it's the consuming project's choice whether to 'opt-in' to the additional plugin. This is usually the best choice for plugins that you publish for public use, because a lot of people will use in setups that you don't control and can't anticipate, so your plugin will be flexible and easy-going.
e
Thanks Adam. I think in my case, being them in-workspace convention plugins, it's fine to be very opinionated. The plugins I'm setting up will be used to ease setting up new modules, when required. A job that all my KMP modules will have to do is testing stuff, and I want them to do that in common code, also making use of resource files. The
kotlinx-resources
plugin is what I need to allow loading resource files in every platform. My plan was to require the plugin dependency, e.g.,
Copy code
dependencies {
  ...
  implementation("com.goncalossilva:resources-plugin:0.4.0")
}
And apply that plugin, e.g.,
Copy code
override fun apply(project: Project) {
  project.pluginManager.apply(ResourcesPlugin::class)
  ...
v
That's perfectly fine, though you should probably use
project.apply
directly like
project.apply<ResourcesPlugin>()
🙂
e
Oh nice, the shorter the better. Thanks! Although I've seen examples using plugin manager, and others not using it.
I suppose the same concept can be applied to dependencies too. I could arbitrary choose to include pre-defined implementation dependencies.
v
Both ways are valid, but if the object directly implements
PluginAware
like
Project
, there is no need to go the detour over
pluginManager
. But both should be fine.
And yes, if your convention plugin adds common dependencies to the projects it is applied to is also perfectly fine. You just cannot use type-safe version catalog accessors in a clean way in that case. You either have to use the string-y API for that, or my hack-around from the according GitHub issue, or Groovy as implementation language.
gratitude thank you 1
e
Thanks! The kotlinx-resources plugin has got an accompaining dependency, so I guess adding it by default is the way to go. String is perfectly fine, as long as it's all contained in a single place, like in this case
👌 1
One last question: to make accessing the KMP
commonTest
source set easier from the plugin, I've decided to apply the KMP plugin by default too. Was just wondering, what's the difference between
Copy code
project.apply<KotlinMultiplatformPluginWrapper>()
and
Copy code
project.apply<KotlinMultiplatformPlugin>()
? Or better, let me reword it: applying plugins like this is cool, but what's the best way to understand which class gets activated via the usual
Copy code
plugins {
  id("...") version "..."
}
?
v
You could simply use the ID instead of the class too like
_project.apply_(plugin = "...")
. But to answer your question, open the according
META-INF/gradle-plugins/<plugin-id>.properties
file and check which
implementation-class
is configured.
e
Indeed:
Copy code
implementation-class=org.jetbrains.kotlin.gradle.plugin.KotlinMultiplatformPluginWrapper
Nice, thanks! The reason I'm using the class directly is because I've defined the plugin's dependencies using the version catalog
Copy code
dependencies {
  implementation(libs.kotlin.plugin)
  implementation(libs.kotlinx.resources)
}
v
The "because" I don't understand. If you have the plugin on the classpath by depending on it, it should also be found via ID by having that properties file in the classpath.
e
Oh it is found, yes. My reason was just to avoid specifying an ID a second time, since I'm already specifying one in the dependencies (but via version catalog)
Not sure if it makes sense tho
v
Theoretically, you could probably take the ID from the version catalog using the string-y API too
✔️ 1