Applying a plugin version inside a convention plugin

I would like to know how to have a convention plugin that applies some other plugins but I’m having a really hard time finding information about this online.

I have a multi module gradle setup and I have two gradle projects that both apply the kotlin plugin in their build script like this

// app1/build.gradle.kts and app2/build.gradle.kts
plugins {
  base
  java
  idea
  id("org.jetbrains.kotlin.jvm") as "1.6.10"
}
// Then some supporting implementation statements with supporting dependencies like kotlin-stdlib-jdk8 and kotlin-reflect

I would like to consolidate this logic into my convention plugin that is defined in buildSrc, however I am struggling to figure out how to do this. If I move the plugin definition into my buildSrc/src/main/kotlin/my-common-conventions.gradle.kts exactly as-is I get an error message that having the version defined in the convention plugin isn’t allowed. Invalid plugin request [id: 'org.jetbrains.kotlin.jvm', version: '1.6.10']. Plugin requests from precompiled scripts must not include a version number. Please remove the version from the offending request and make sure the module containing the requested plugin 'org.jetbrains.kotlin.jvm' is an implementation dependency of project ':buildSrc'. So I can remove the version number from the kotlin plugin and the it builds okay.

However, I want to know how I can pin the plugin definition to a specific version, and more than that I would like to know the best practice. I know that regular dependencies defined in the depenendencies block with implementation/api are included in the convention plugin, even when versions are specified. But somehow plugin versions in the convention plugin’s plugin block are different. How can we use a common configuration across projects that implements a plugin’s version number?

1 Like

I had to do this exact thing.

buildSrc/build.gradle.kts needs to have the Maven dependencies of the plugins instead of the ID:

plugins {
    `kotlin-dsl`
}

dependencies {
    implementation("org.jetbrains.kotlin:kotlin-gradle-plugin:1.6.10")
}

// Not sure if this is necessary or not
// Add it if it is not able to find the dependencies
repositories {
    gradlePluginPortal()
}

Then in your convention plugin, you just omit the version.

You can find the correct Maven dependency in the legacy section of the plugin page:

https://plugins.gradle.org/plugin/org.jetbrains.kotlin.jvm

1 Like

An easier variant without needing to look up the artifact coordinates is to use the marker artifact.
implementation("org.jetbrains.kotlin.jvm:org.jetbrains.kotlin.jvm.gradle.plugin:1.6.10").
It is always <plugin id>:<plugin id>.gradle.plugin:<version>.

6 Likes

@Vampire Wow! I was totally unaware of that. That is fantastic. Looks like that is documented here:

https://docs.gradle.org/current/userguide/plugins.html

3 Likes

Thanks for the help guys!

Emmm. But the Kotlin official documentation doesn’t mention the plugin id. As an instead they prefer to use kotlin("jvm"), and it cannot be used in dependencies block.

That’s why I don’t like to use the buildSrc
(Sorry I’m not noticed that the thread is 2 years old.)

But the Kotlin official documentation doesn’t mention the plugin id

That’s not correct.
If you switch an example that uses kotlin("...") from “Kotlin” mode to “Groovy” mode you instead see the actual plugin id org.jetbrains.kotlin.... being used.
The kotlin("...") syntax actually also is not coming from Kotlin, but is built-in into Gradle.
And its docs kotlin also link to the Gradle Plugin Portal search that shows all the available plugins including their ID: Gradle - Plugins.
For example Gradle - Plugin: org.jetbrains.kotlin.jvm for kotlin("jvm").

1 Like