Search code examples
kotlinbuild.gradlegradle-kotlin-dsl

Externalize Task in build.gradle.kts


Currently I do have the configuration for all gradle-Tasks in the central build.gradle.kts. Since this file is going to get too long, I am planning to exernalize at least some of the tasks to their own files.

Currently my build.gradle.kts looks somewhat like the following:

import org.asciidoctor.gradle.jvm.AsciidoctorTask

val revDate = System.getenv()["revdate"] ?: SimpleDateFormat("yyyy-MM-dd").format(Date())
val revNumber = System.getenv()["revnumber"] ?: "DEV-Version"

plugins {
...
    id("org.asciidoctor.jvm.convert") version "3.1.0"
...
}

tasks.withType<AsciidoctorTask>().configureEach {
    setSourceDir(file("src/docs"))
    setOutputDir(file("$buildDir/docs"))

    attributes(
        mapOf(
            "source-highlighter" to "rouge",
            "toc"                to "left",
            "toclevels"          to 2,
            "idprefix"           to "",
            "idseparator"        to "-",
            "revnumber"          to "$revNumber",
            "revdate"            to "$revDate"
        )
    )
}

The above build.gradle.kts generates my documentation if calling the asciidoctor-Tasks. Now I have tried to externalize the above configuration by using

apply {
    from("gradle/asciidoctor.gradle.kts")
}

inside the build.gradle.kts and furthermore defining the above used file:

#gradle/asciidoctor.gradle.kts
import org.asciidoctor.gradle.jvm.AsciidoctorTask

buildscript {
    repositories {
        gradlePluginPortal()
    }
    dependencies {
        classpath("org.asciidoctor:asciidoctor-gradle-jvm:3.1.0")
    }
}

apply{
    plugin("org.asciidoctor.jvm.convert")
}

tasks.withType<AsciidoctorTask>().configureEach {
    setSourceDir(file("src/docs"))
    setOutputDir(file("$buildDir/docs"))

    attributes(
        mapOf(
            "source-highlighter" to "rouge",
            "toc"                to "left",
            "toclevels"          to 2,
            "idprefix"           to "",
            "idseparator"        to "-",
            "revnumber"          to "$project.revNumber",
            "revdate"            to "$project.revDate"
        )
    )
}

Unfortunately, this does not work correctly and gives me an exception, that the plugin with the given id ('org.asciidoctor.jvm.convert') is not found.

I am using gradle 6.6.1.

What am I missing, what should I do differently?


Solution

  • In an included script, you only get the default environment. You have no access to plugins that are applied in the main project file and you cannot apply any additional plugins. This is different from the Groovy DSL and there is no way around it.

    Instead, you have to put this logic into buildSrc. Gradle Kotlin offers pre-compiled script plugins that make this quite easy. You create a file buildSrc/src/main/kotlin/my-plugin.gradle.kts and add the same code in there as you would have added in the included script.

    Then, in your project, you can add this in the plugins block:

    plugins { 
        `my-plugin`
    }
    

    In addition, buildSrc/build.gradle.kts has to contain:

    plugins {
        `kotlin-dsl`
    }
    
    repositories {
        jcenter()
        gradlePluginPortal()
    }
    

    For more information, see the Gradle documentation.