I'm trying to understand all the ways you can apply a plugin in Gradle, Kotlin DSL. This question answers part of my question, but not all of it (I'm guessing methods have been added in the six years that have passed since them).
I've seen this exact scenario in one of my build.gradle.kts
files.
plugins{
`kotlin-dsl`
kotlin("jvm") version "1.6.10"
id("com.foo.bar.someplugin") version 1.2.3
}
apply("foo2.bar2.anotherplugin")
Wow, that's four different ways to apply a plugin and I don't really understand the relationship between them at all. From the other answer, I get that apply(...)
is the legacy way and will eventually be deprecated, but what about the other three?
Furthermore, I'm confused by why the `kotlin-dsl`
doesn't even need a version. What is this voodoo magic?
And finally, for the sake of consistency, I would like to standardize the plugins block (let's ignore the apply(...)
since it's legacy functionality) so that everything uses id(...)
. How do I convert the other two?
There is actually only 2 mechanisms, which you already identified:
apply
plugins
blockYour plugins block seems to have multiple approaches, but those are really just helpers for the second mechanism:
id("some.plugin.id") version "1.2.3"
is the basic way of adding a plugin with an ID and a versionkotlin("...")
is a helper function provided by the Kotlin DSL that calls id()
behind the scenes with a org.jetbrains.kotlin.
prefix before whatever string you passed. So kotlin("jvm")
is just a shorthand for id("org.jetbrains.kotlin.jvm")
kotlin-dsl
is also a helper function that is a shortcut for the Kotlin DSL Gradle plugin. I believe the string ID is org.gradle.kotlin.kotlin-dsl
.In the legacy way of applying plugins, you had to declare the dependency on the plugin in the buildscript
block so the classes of the plugin are added to the classpath for the compilation/execution of the Gradle script itself. As a second step, calling apply
would actually apply the plugin to the current project.
The plugins
block was introduced to streamline this and make it more convenient. When you add a plugin there, it is both added to the classpath AND applied to the project.
You can still choose to only add a plugin to the classpath without applying it to the current project by adding apply false
after the plugin declaration:
plugins {
id("com.foo.bar.someplugin") version 1.2.3 apply false
}
This is useful if you want to declare all plugins and their versions in the root project, and then just apply the relevant ones in subprojects by using the plugins
block without versions:
plugins {
id("com.foo.bar.someplugin")
}
Furthermore, I'm confused by why the
kotlin-dsl
doesn't even need a version. What is this voodoo magic?
As you can see from the above explanation, any plugin that's already on the classpath doesn't need a version. This applies to plugins that are already declared in a parent project, or in the settings.gradle(.kts)
's plugins
, and to built-in Gradle plugins.
The Kotlin DSL plugin (kotlin-dsl
) is a built-in Gradle plugin, so it uses a version that's dependent on the version of Gradle you are using. It is similar to the java
or application
plugins.
It's also explicitly advised to avoid specifying the version for it in the doc:
Avoid specifying a version for the kotlin-dsl plugin. Each Gradle release is meant to be used with a specific version of the kotlin-dsl plugin and compatibility between arbitrary Gradle releases and kotlin-dsl plugin versions is not guaranteed. Using an unexpected version of the kotlin-dsl plugin in a build will emit a warning and can cause hard to diagnose problems.
I would like to standardize the plugins block (let's ignore the apply(...) since it's legacy functionality) so that everything uses id(...). How do I convert the other two?
The way they are written here is quite idiomatic, so this should be considered the "standard". This is actually how it's advised to be used in the doc. Using kotlin-dsl
is a nice way to distinguish built-in Gradle plugins from third party plugins. Also, it is a type-safe way to declare the plugin, it's understood by the IDE and you can search for references etc. Strings are just inferior in this respect.
If you really really wanted to apply it with the string-based syntax, you could probably use id("org.gradle.kotlin.kotlin-dsl")
, but I've never seen a project do that so far, and I even had to search for this ID which is never advertised anywhere.
The kotlin()
helper could be more debatable, and a matter of personal taste, but IMO the less arbitrary strings, the better.