That's Gonna Leave A Mark - Gradle Plugin Markers
Posted on 2025-03-05

You’ve likely encountered plugin declarations like this:

plugins {
    id("com.android.library") version("8.9.0")
    id("maven-publish")
}

And you might have wondered how Gradle locates these plugin. This post aims to demystify that process.

The simpler aspect is that Gradle includes a set of plugins within its distribution, known as core plugins. Examples include id("java-library"), id("maven-publish"), and "id(signing"). Since these plugins are part of the Gradle distribution, their JAR files are already present on your machine by when you execute Gradle.

The more intricate part involves community plugins that are hosted on Maven repositories. By default, Gradle searches for plugins exclusively on Gradle Plugin Portal. However, you can extend this search by configuring additional repositories your in settings.gradle.kts file:

pluginManagement {
    repositories {
        google()
        mavenCentral()
        gradlePluginPortal()
    }
}

Plugins are essentially JVM libraries. To translate a plugin ID to its corresponding Maven coordinates, Gradle uses Plugin Marker Artifacts. These act as transparent redirects.

For instance, when you declare id("com.android.library) version("8.9.0"), Gradle attempts to retrieve com.android.library:com.android.library.gradle.plugin:8.9.0 from each repository specified in your settings.gradle.kts. Ultimately, it fetches the POM file, which contains a dependency on the actual plugin implementation:

  <dependencies>
    <dependency>
      <groupId>com.android.tools.build</groupId>
      <artifactId>gradle</artifactId>
      <version>8.9.0</version>
    </dependency>
  </dependencies>

A significant advantage of Plugin Markers is that you relocate a plugin’s implementation to a different Maven coordinate without requiring any modifications from end-users.

If you are developing a binary Gradle plugin and need to configure another plugin, such as id("com.android.library), you can include its marker artifact as a compileOnly dependency:

dependencies {
    compileOnly("com.android.library:com.android.library.gradle.plugin:8.9.0")
}

To streamline this process, you can create a helper function to generate the Maven coordinate from a plugin ID and version:

fun idToMavenCoordinate(id: String, version: String): String {
    return "$id:$id.gradle.plugin:$version"
}