A simple question: how does gradle deal with plugins that are compiled against a version of the gradle api that is different from the version of gradle used during the build?
My build is using Gradle 6.3, but some plugins I use seem to compiled against gradle-api 3.0. What is the correct way to deal with that? I don’t really understand how this is supposed to work at all, if plugins aren’t compiled against exactly the same version the build is using.
For one, a relatively stable API from the Gradle folks. OK so they have sometimes broken things accidentaly, but they are good at managing deprecations.
Secondly, there are things a plugin author can do to deal with compatibility over a wide range of releases. To elaborate will take far more than a reply here, but a couple of highlights should do for now:
The Grolifant library aids plugin authors to deal with recurring themes and keep compatibility. Up to 0.16 it supports Gradle 3.0 - 6.3.
Test for compatibility using Gradle’s own TestKit library, the GradleTest plugin or the Stutter library
Understanding that if you write plugins in Groovy that you might have to forego certain Groovyisms as they do not survive major changes in Groovy versions.
Writing plugins in Java & Kotlin can help in a certain way with the previous issue, but that also have drawbacks especially when there are breaking changes in the API ebtwwen major Gradle versions.
Understanding that when Java/Kotlin is the obstacle, using Groovy actually works better again by a combination of statically compiled APIs, but some internal methods implemented dynamically.
Ok, but how does Gradle prevent two versions of the Gradle API being present on the classpath? If my plugin is packaged as a maven module with a POM and has a dependency on some gradle api version, I noticed that the classpath of a Worker process contained two jars for Gradle API with different versions. Am I doing something wrong is this how it’s supposed to work?
It’s not supposed to work that way. Normally gradleApi() behaves the same way as a dependency placed iin Maven “provided” scope. In other words your POM should not explictly declare it as a runtime dependency as Gradle will provide it.
(I originally assumed you are building the plugin with Gradle, but are you building it with Maven?)