gradlegradle-multi-project-build

How can you apply a plugin written as a Kotlin class to a Kotlin script plugin in Gradle


I have a Gradle multi-module project.

If I:

  1. Apply a Kotlin class plugin to another Kotlin class plugin: It's ok.

  2. Apply a Kotlin script plugin to another Kotlin script (.kts) plugin: It's ok.

  3. Apply a Kotlin script plugin to a Kotlin class plugin: It's ok.

  4. Apply a Kotlin class plugin to Kotlin script (.kts) plugin: Error.

So when I apply a Kotlin class plugin to a Kotlin script (.kts) plugin, an error occurs saying that the plugin cannot be found.

Why doesn't it work in this case? I can't find a solution.


Solution

  • In order for a script plugin to use a class plugin, the class plugin code must be on the classpath of the script plugin compilation (docs). Unfortunately the source files of the compilation of the same project are not added to that classpath.

    Instead, this can be done by adding the class plugin to the implementation configuration in the buildscript for the script plugin.

    If this is the same project where the class plugin code is located (in many cases buildSrc), this is not going to work as you'd end up with a circular dependency. So you are going to have to move your class plugin code to a new project.

    You can do this by using an included build. To do this:

    1. Add a new directory (eg classPlugins) somewhere in your main project tree
    2. Add a settings.gradle.kts file and a build.gradle.kts file to that directory
    3. Write the build.gradle.kts file in the normal way for a plugin project, plus include group and version coordinates:
    plugins {
        `kotlin-dsl`
    }
    
    repositories {
        mavenCentral()
    }
    
    gradlePlugin {
        plugins {
            create("myPlugin") {
                id = "myClassPlugin"
                implementationClass = "mypackage.MyClass"
            }
        }
    }
    
    group = "t2k2ej"
    version = "1.0.0"
    
    1. Include the new build in your main project's settings.gradle.kts
    includeBuild("classPlugins") // Put the relative path from the root to the new build
    
    1. Add the new build to the classpath in your script plugin project (probably buildSrc):
    dependencies {
        implementation("t2k2ej:classPlugins:1.0.0")
    }
    
    1. Finally, you can now apply the class plugin in your script plugin:
    plugins {
        id("myClassPlugin")
    }