Open DreierF opened 9 months ago
@DreierF I re-discovered the workaround for this issue I did in another build:
tasks.withType<ShadowJar>().configureEach {
// Defer the resolution of 'runtimeClasspath'. This is an issue in the shadow
// plugin that it automatically accesses the files in 'runtimeClasspath' while
// Gradle is building the task graph. The three lines below work around that.
inputs.files(project.configurations.runtimeClasspath)
configurations = emptyList()
doFirst { configurations = listOf(project.configurations.runtimeClasspath.get()) }
}
A better workaround that also works with configuration cache:
tasks.withType<ShadowJar>().configureEach {
// Do not resolve too early through 'dependencyFilter'
dependencyFilter = NoResolveDependencyFilter()
}
class NoResolveDependencyFilter : DefaultDependencyFilter(project) {
override fun resolve(configuration: FileCollection): FileCollection {
return configuration
}
}
We've run into this too. It occurs to me both the resolution of artifacts at configuration time, and the problem with the missing inputs could be addressed by returning a detached configuration that extendsFrom
the requested configurations.
That will let Gradle defer calculation of the classpath input until execution time, and also ensure that implicit dependencies on the tasks that produce the artifacts are wired.
Related upstream issue: https://github.com/gradle/gradle/issues/26155
Thanks for the issue link @DanielThomas. I have been searching for that one.
Shadow Version
8.1.1
Gradle Version
8.3
Expected Behavior
I can use artifact transforms on my dependencies in combination with the shadow plugin to shade the result of the transformed dependencies.
Actual Behavior
When the
runtimeClasspath
requires an artifact transform running theshadowJar
task results inAccording to @jjohannes this is caused by dependency resolution being triggered too early. There is only a particular window between the "main" configuration time and before any task starts in which transforms should/can run. But Gradle does not check that well and you get unexpected/inconsistent errors. This
resolve()
is triggered during configuration time. TheresolvedConfiguration
access here seems to be the problematic part. That should not be done and instead the filtering implemented there should be done lazily at a later point. It breaks transforms.Reproduction
A full minimal reproduction setup can be found here: reproduction-gradle-shadow-artifact-transform. It consists of an app module and a lib module and a NoOp artifact transform. The error can be reproduced with
./gradlew clean shadowJar
.Workaround
In case other people run into this: I worked around the issue for now by running
./gradlew jar && ./gradlew shadowJar
in CI, because it firsts builds the expected jar files and then can pick them up during the second invocation. This is quite a hacky solution, but the only thing I could get to work.