PaperMC / paperweight

Gradle build system plugin for Paper and Paper forks

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Reobf jar variant points to the wrong artifact location when using Groovy DSL

0dinD opened this issue · comments

Paperweight version: 1.3.5
Gradle version: 7.3.3
Minimal example repo to reproduce the issue: https://github.com/0dinD/paperweight-bug

I have a submodule for NMS code that uses paperweight-userdev. I now want to depend on the reobfuscated jar artifact from the submodule in the main plugin module. So i do something like this:

dependencies {
    runtimeOnly project(path: ":nms-submodule", configuration: "reobf")
}

For context, the NMS submodule is bundled into the plugin using Shadow and then loaded dynamically based on the server version, similar to how WorldEdit and other plugins do it.

But when I build the shadow jar, it doesn't contain the classes from the NMS submodule. Running ./gradlew clean shadowJar --info yields the following information in the output:

> Task :shadowJar
file or directory '/path/to/paperweight-bug/nms-submodule/.gradle/caches/paperweight/taskCache/reobfJar.jar', not found

This prompted me to check ./gradlew :nms-submodule:outgoingVariants, which reports:

--------------------------------------------------
Variant reobf
--------------------------------------------------
Capabilities
    - org.example:nms-submodule:1.0.0-SNAPSHOT (default capability)
Attributes
    - io.papermc.paperweight.obfuscation = obfuscated
    - org.gradle.category                = library
    - org.gradle.dependency.bundling     = external
    - org.gradle.libraryelements         = jar
    - org.gradle.usage                   = java-runtime

Artifacts
    - .gradle/caches/paperweight/taskCache/reobfJar.jar (artifactType = jar)

So the problem is that the reobf variant points to the wrong artifact location, a temporary jar in the cache which gets deleted before the Shadow plugin can use it.

Strangely enough, this only happens when using the Groovy DSL, not the Kotlin DSL (even when the build scripts are identical). You can see this by renaming the nms-submodule/build.gradle file in my example repo to build.gradle.kts (no other changes required). Inspecting the output of ./gradlew :nms-submodule:outgoingVariants I would expect that the correct artifact location gets assigned even when using the Groovy DSL.

I see that the artifact location is assigned here:

reobfJar {
inputJar.set(devJarTask.flatMap { it.archiveFile })
outputJar.convention(archivesName.flatMap { layout.buildDirectory.file("libs/$it-${project.version}.jar") })
}

My best guess is that the afterEvaluate above is causing issues, but I'm not sure why it would work in the Kotlin DSL if it doesn't work in Groovy. Before afterEvaluate runs the output location seems to be set from

outputJar.convention(defaultOutput())

and it looks like defaultOutput() is .gradle/caches/paperweight/taskCache/reobfJar.jar.

Now, I did manage to come up with a workaround, by manually assigning the correct artifact location:

configurations.reobf {
    outgoing.artifact(layout.buildDirectory.file("libs/${project.name}-${project.version}.jar"))
}

I don't know enough about the internals about this plugin to know what the proper solution is, but maybe the output location should be set before afterEvaluate? Or maybe this is just a Gradle bug, in which case I can open a bug report there instead. Or perhaps I've misunderstood something and there's a better solution, which I'd be happy to hear.

Something about https://github.com/0dinD/paperweight-bug/blob/3aa5e892186874faae7cce1ba732653cc1f21aad/nms-submodule/build.gradle#L21-L23 looks to be causing publications to be evaluated early with groovy.

Running with groovy: https://paste.gg/p/anonymous/8f510999dc134427a934470dd4d85fde
With kotlin: https://paste.gg/p/anonymous/4a17773046864caa9528f7d3538dff4e

Changing the linked lines to

tasks.named("assemble") {
    dependsOn(tasks.named("reobfJar"))
}

allowed it to work as expected with a groovy script: https://paste.gg/p/anonymous/dea12e03702c40a8967e26bf27eaa044

Ah, I think I see what's happening now. Those lines were pretty much taken from:

https://github.com/PaperMC/paperweight-test-plugin/blob/3e3ba3d0454e78ccfd90c6b398d1f8716a8c37ee/build.gradle.kts#L28-L32

So that's why I assumed the problem was related to something else. But for whatever reason, the Groovy DSL behaves differently from the Kotlin DSL in this instance, see gradle/gradle#15720. So in the Groovy DSL you currently need to use the more verbose tasks.named notation for task configuration avoidance, like you did in your example.

Thanks for helping me figure this out!