How to apply binary plugin from convention plugin

Hello Gradle community,

I have a project using Gradle 8.4 with some binary plugins from buildSrc defined in buildSrc/build.gradle.kts using:

gradlePlugin {
  plugins {
    create("instrument-plugin") {
      id = "instrument"
      implementationClass = "InstrumentPlugin"
    }
    // Some more create(...)
  }
}

And I am trying to apply thoses plugins as part of a convention plugin, also defined in buildSrc in buildSrc/src/main/kotlin/instrumentation.gradle.kts using either:

plugins {
  id("instrument")
}

or:

project.pluginManager.apply("instrumenter")

My issue is the binary plugin instrument is not found when applying the convention plugin instrumentation:

An exception occurred applying plugin request [id: 'instrumentation']
> Failed to apply plugin 'instrumentation'.
   > Plugin with id 'instrumenter' not found.

Can you help me to figure where the issue is and how to structure my build? Thanks :pray:
For reference, the project is open source and available an GitHub.

Besides that you should add at least one dot to the plugin IDs to prevent potential clashes with built-in pluigns which should be the only ones without namespace, your plugin is called instrument not instrumenter.

That you cannot use it in the plugins block is expected, as that is a chicken-and-egg problem. While building buildSrc the plugin is not yet available and thus cannot be applied using the plugins block, as the plugins blocks of precompiled Kotlin DSL script plugins are extracted and applied to a dummy project to find out which type-safe accessors to generate.

For applying one precompiled script plugin in a sibling one, there is special support that makes it work, but for binary plugins, this does not work.

So either use project.apply(plugin = "instrument"), or by using the class, not the ID.

Hey @Vampire :wave:
Thanks for you anwer!

your plugin is called instrument not instrumenter .

My bad. I fixed it and introduced better plugin identifiers. That works way better.

as the plugins blocks of precompiled Kotlin DSL script plugins are extracted and applied to a dummy project to find out which type-safe accessors to generate.

Thanks for the explanation. That makes things way better to understand!


Another similar question is I am trying to apply a released plugin (kotlin) from a reusable script plugin gradle/test-with-kotlin.gradle:

buildscript {
  repositories {
    maven {
      url "https://plugins.gradle.org/m2/"
    }
  }
  dependencies {
    classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:1.6.21"
  }
}

apply plugin: "org.jetbrains.kotlin.jvm"
// Also tried: apply plugin: "kotlin" 

// Some other task config

That I include in my build.gradle files using: apply from: "$rootDir/gradle/test-with-kotlin.gradle".
Doing so gets me the following error:

A problem occurred evaluating script.
> Plugin with id 'org.jetbrains.kotlin.jvm' not found.

I get those part from the plugin repository and it feels to only find the plugin if the repository/dependencies parts are store directly in the build.gradle, but not the test-with-kotlin.gradle script. There might be something I am doing wrong here too.

There might be something I am doing wrong here too.

Basically, that you use legacy script plugins (the ones you do “apply from”) at all.
They are highly discouraged and have quite some quirks and shortcomings.
Better make it a convention plugin too (no matter whether as binary plugin or as precompiled script plugin).
Could very well be, that those quirks are biting you there.