Deprecation warning

> Task :hibernate-core:forbiddenApisNonPortable
Execution optimizations have been disabled for task ':hibernate-core:forbiddenApisNonPortable' to ensure correctness due to the following reasons:
  - Gradle detected a problem with the following location: '/home/sebersole/projects/hibernate-orm/6.0/hibernate-core/target/classes/java/main'. Reason: Task ':hibernate-core:forbiddenApisNonPortable' uses this output of task ':hibernate-core:forbiddenApisSystemOut' without declaring an explicit or implicit dependency. This can lead to incorrect results being produced, depending on what order the tasks are executed. Please refer to https://docs.gradle.org/7.3.3/userguide/validation_problems.html#implicit_dependency for more details about this problem.

Gradle complains that forbiddenApisNonPortable defines an “implicit dependency” on forbiddenApisSystemOut because it reuses the output from forbiddenApisSystemOut. Both tasks are of type CheckForbiddenApis (Gradle - Plugin: de.thetaphi.forbiddenapis) which does not define outputs.

All of these CheckForbiddenApis tasks really only depend on compiling the sources, and they define explicit dependencies on that task:

task forbiddenApisSystemOut(type: CheckForbiddenApis, dependsOn: compileJava) {
    ...
}

task forbiddenApisNonPortable(type: CheckForbiddenApis, dependsOn: compileJava) {
    ...
}

(hibernate-orm/java-module.gradle at 9335d3efbf96d4cbe4a7d9aa79193882328b2415 · dreab8/hibernate-orm · GitHub)

Seems like just a bug, or am i missing something?

java.module.gradle line 545-547:

project.tasks.withType( CheckForbiddenApis ).each { task ->
	task.outputs.dirs project.sourceSets.main.output.classesDirs
	task.classesDirs = project.sourceSets.main.output.classesDirs

So all these tasks have the project.sourceSets.main.output.classesDirs and project.sourceSets.main.output.classesDirs as inputs and outputs which per-se is bad already as a task should never have the inputs also as outputs or it immediately makes itself out-of-date again.

Btw. every time you use an explicit dependsOn that is also a sign of code-smell. It is better if you have proper output properties wired to proper input properties and thus getting implicit task dependencies as needed.

Btw. even if not an individual task has the same as input and output, it is also bad if all three tasks just have the same output defined. Overlapping outputs are always problematic as then up-to-date checks cannot work reliably and there might get bad entries into the build cache for example.

The tasks simply define no output. I cannot control that. But I was able to hack it better (the current source you looked at was just a poor, previous attempt to hack it) -

project.tasks.withType( CheckForbiddenApis ).each { task ->
    def outputFile = project.file( "${buildDir}/forbidden-apis/${task.name}-output.txt" )
    ...
    task.outputs.file outputFile
    ...
    task.doLast {
        outputFile.parentFile.mkdirs()
        outputFile.createNewFile()
    }	
}

Does that mean the task just has no output and you simply register and create that outputfile so that there is something the up-to-date check sees as output and can be up to date?

Then the proper way is to use

outputs.upToDateWhen { true }

instead.

1 Like