Imagine a Kotlin build script like this:
plugins {
`java-base`
`maven-publish`
}
publishing {
println("Inside publishing {}")
publications {
println("Inside publications {}")
register<MavenPublication>("maven") {
println("Inside maven {}")
val javadoc by tasks.getting
artifact(tasks.get("javadoc"))
pom {
name = "test"
}
}
}
}
tasks {
println("Inside tasks {}")
register<Jar>("javadoc") {
println("Inside javadoc {}")
archiveClassifier.set("javadoc")
}
}
The intent here is simple: to create a “maven” publication and attach Javadocs to it. This build script, I believe, uses all the “configuration avoidance” feature, like register to lazily register Named Domain Objects: Tasks and Publications.
As far as I expect from this “laziness”, Gradle should first execute the build whole build script itself, but not the register blocks closures. So here publishing.publications and tasks should be executed first, and then the appropriate register<MavenPublication>("maven") or register<Jar>("javadoc") blocks, if they are needed.
Yet the output of the ./gradlew publishToMavenLocal with this script (note those printlns here and there) is:
Inside publishing {}
Inside publications {}
Inside maven {}
FAILURE: Build failed with an exception.
* Where:
Build file '/home/madhead/Projects/tmp/build.gradle.kts' line: 34
* What went wrong:
Could not create domain object 'maven' (MavenPublication)
> Task with name 'javadoc' not found in root project 'tmp'.
So, it never executes the tasks block, but instead jumps straight into the “maven” publication configuration. Obviously, it cannot find the “javadoc” task definition because the tasks block was not executed yet, so it fails.
The fix is simple: place the tasks block before the publishing block:
plugins {
`java-base`
`maven-publish`
}
tasks {
println("Inside tasks {}")
register<Jar>("javadoc") {
println("Inside javadoc {}")
archiveClassifier.set("javadoc")
}
}
publishing {
println("Inside publishing {}")
publications {
println("Inside publications {}")
register<MavenPublication>("maven") {
println("Inside maven {}")
val javadoc by tasks.getting
artifact(tasks.get("javadoc"))
pom {
name = "test"
}
}
}
}
It works as expected: first it executes the tasks block but does not configure the “javadoc” task. Then it executes all the publications related code (including the “maven” publication configuration, which is required for the publishToMavenLocal task), and in the middle of that configuration it actually instantiates the “javadoc” task
Inside tasks {}
Inside publishing {}
Inside publications {}
Inside maven {}
Inside javadoc {}
BUILD SUCCESSFUL in 1s
3 actionable tasks: 2 executed, 1 up-to-date
What am I missing here? Why is the “maven” publication configuration is eager and not lazy here? How do I make it lazy?