To apply Gradle plugins from within buildSrc plugins you need to do two things
Add the plugins as dependencies in buildSrc/build.gradle.kts
Plugins must be added as dependencies using the Maven coordinates, not the plugin ID†. The Maven coordinates of plugins can be found in the Gradle plugin portal.
// buildSrc/build.gradle.kts
plugins {
`kotlin-dsl`
}
dependencies {
// the Maven coordinates of the Kotlin Gradle and Serialization plugins
implementation("org.jetbrains.kotlin:kotlin-gradle-plugin:1.7.20")
implementation("org.jetbrains.kotlin:kotlin-serialization:1.7.20")
}
apply the plugins, either using the class, or the plugin ID.
(Note that kotlin("jvm")
is a helper function that obscures the actual Gradle plugin ID, which is org.jetbrains.kotlin.jvm
)
class MyPlugin: Plugin<Project> {
override fun apply(project: Project) {
project.pluginManager.apply("org.jetbrains.kotlin.jvm")
project.pluginManager.apply("org.jetbrains.kotlin.plugin.serialization")
// the plugin class for the Kotlin JVM & Serialization plugins
project.plugins.apply(org.jetbrains.kotlin.gradle.plugin.KotlinPluginWrapper::class)
project.plugins.apply(org.jetbrains.kotlinx.serialization.gradle.SerializationGradleSubplugin::class)
}
}
(it wasn't easy to find the plugin classes - I had to dig around in the jar to find the plugin marker artifact, e.g. kotlin-serialization-1.7.20-gradle71.jar!/META-INF/gradle-plugins/org.jetbrains.kotlin.plugin.serialization.properties
)
Precompiled script plugins
You might also like to use precompiled script plugins. They allow for writing buildSrc script plugins that much more similar to standard build.gradle.kts
files, and so you can apply plugins in the plugins block.
// buildSrc/src/main/kotlin/conventions/kotlin-jvm.gradle.kts
plugins {
kotlin("jvm")
}
To enable precompiled script plugins, make sure you've applied the kotlin-dsl
plugin in buildSrc/build.gradle.kts
.
// buildSrc/build.gradle.kts
plugins {
`kotlin-dsl`
}
Error: Plugin request for plugin already on the classpath must not include a version
What happens when you apply the above steps and you get an error Plugin request for plugin already on the classpath must not include a version
?
There are a lot of ways to specify the version of a Gradle plugin (far too many in my opinion!). If you're updating an existing project with the above steps, you've just used one more way of specifying a version, and Gradle is spitting out an unhelpful error message.
The way to fix it is to limit the number of ways your project specifies Gradle plugin versions. What's probably happened is that you've added a plugin in buildSrc/build.gradle.kts
that you also apply in the plugins block of a subproject. Gradle will get confused about which version of the plugin you want.
The way to fix it is to only specify the plugin version in a single place, and that place is as a dependency in buildSrc/build.gradle.kts
.
// my-cool-subproject/build.gradle.kts
plugins {
kotlin("jvm")// version "1.9.0" // version is not necessary, it's specified in buildSrc/build.gradle.kts
}
Footnotes
† Note that it is actually possible to use the plugin ID as a regular dependency, with some manipulation. Gradle can discover plugins from any Maven repository via the Plugin Marker Artifact. Given a plugin ID the Maven GAV coordinates can be determined as follows:
val kmpPluginId = "org.jetbrains.kotlin.multiplatform"
val kmpPluginVersion = "1.9.0"
val kmpMavenGav = "${kmpPluginId}:${kmpPluginId}.gradle.plugin:${kmpPluginVersion}"