Implicit task dependency

The jandex-gradle-plugin-0.9.0 had an issue with Gradle 7 where the out put of the jandex task was consumed by the jar task but there was no explicit dependency between the two, Gradle flagged this and disabled execution optimizations. See Gradle 7 makes optimizations disabled · Issue #9 · kordamp/jandex-gradle-plugin · GitHub

The fix “appeared to be” the following: make jar depend on jandex.
Note that jandex depends on classes and that classes is finalized by jandex. This ensures that the jandex index will be generated when classes are recompiled, right?

Now there’s another issue but this time with compileTestJava and test. See gradle 7 · Issue #11 · kordamp/jandex-gradle-plugin · GitHub

Again, Gradle 7 flags that these 2 tasks depend on the output of jandex but there’s no direct dependency between them. We’ve already established that jandex will run after classes because its a finalizer (finalizer tasks are guarantee to run even if the “finalizee” failed, right?) thus the output of the jandex task is ready way before compileTestJava and test are invoked, yet the error message states this might not be true.

So I ask, what’s the proper way to fix this? Are finalizing tasks not recommended for this use case? Or if they are, is this a bug?

Hi Andres,

a finalizer task for Gradle means that it will run after the task it finalizes, like for example your jandex task will run after the classes task. While Gradle tries to schedule the finalizer tasks as close to the finalized task as possible, there are no guarantees. In your case, that means that the jandex task is not guaranteed to run before the jar or the test task, and that is why the warning is correct.

What you are trying to do is to insert a task between the classes task and all the tasks which depend on the classes task to add something more to the jar depending on the compiled classes. This is not easy today on a task level. What you could do instead would be to depend on the output of the source set you run the jandex task for, or even on the output.classesDirs of the sourceSet and then have classes depend on the jandex task.

Cheers,
Stefan

Stefan, I am afraid it would cause cyclic dependency (see https://gradle-community.slack.com/archives/CA7UM03V3/p1614090667026700 , https://gradle-community.slack.com/archives/CA7UM03V3/p1609945983237100 )

Thank you for the pointer, @vlsi. I feared something like that :frowning:
So Stefan Oehmes comment is probably the best current solution:

What I do to work around this is this:

  • Explicitly list all the compile tasks as an input to my generator
  • Register the generator as a sourceSet output, so that everything downstream works as normal

@vlsi Did you end up filing an issue?

Not really :slight_smile:

I see there’s Allow to run bytecode instrumentation after all compilation tasks · Issue #2137 · gradle/gradle · GitHub and Task consuming `sourceSet.output.classesDirs` can’t add its output to that SourceSet · Issue #12774 · gradle/gradle · GitHub which seems to cover the similar use-case

Thanks, however explicitly listing all compile tasks is not even the correct solution for this very specific use case as witnessed by Gradle 7 makes optimizations disabled · Issue #9 · kordamp/jandex-gradle-plugin · GitHub the jacocoTestReport task was also affected.

As it looks to me, the way jandex inserts itself right now in the graph affects every consumer of the main sourceset. It’s easy to think that this affects compile classes but in reality the effects can be seen further down the graph.

I was not aware of the timing issues with finalizers, I guess I’ll have to try another approach, but listing all possible consumers ahead of time from a plugin’s POV is likely not feasible in all cases.