Build output can be wrong when projectDir/.gradle does not exist

We have encountered the following case of the build producing bad output, steps to reproduce are;

  1. run gradle clean 2) Add a new class, the compiled class will end up in the build directory 3) Delete the source class

  2. Delete the project’s root .gradle folder

  3. Do another build. The class file will remain in the build directory.

If one were to produce a jar from this build, it would contain the “bad” class. As far as I can see the 2nd build completes normally and sees that it has no record of the compile task running so executes it.

Any ideas on the root cause for this? My guess is that in normal circumstances, when it has a view of what the output was last time, it is able to work out that the deleted class is no longer in the input so should not be in the output (or some variation on this).

It seems like the correct behaviour should be to treat every project build as untrusted if it runs and finds that .gradle does not exist but a build dir does. I don’t know enough about how gradle caches work to be sure on that though.

The problem is specific to the ‘CompileJava’ task. This task cleans its own files (i.e. those it produced last time) before it runs to get rid of stale class files. If you delete ‘.gradle’, the history is gone, and it can’t delete them anymore.

This problem could be solved by making the ‘CompileJava’ delete its whole output directory before it runs. But then you’ll run into problems if other tasks are writing into the same output directory. For example, some people use the same output directory for classes and resources. Formerly this was even the default.

In summary, I’m not quite sure what to do about this. Of course, you can always add a ‘doFirst {}’ action to your compile tasks that cleans their output directories.

ok thanks. I think I will just make all tasks depend on clean if projectCacheDir doesn’t exist, bit brute force but is fine for me.

since gradle has a list of all the files that a task outputs, could it possibly compare that list to what is actually in the output directory and delete stale class/resource files?

That’s exactly what the ‘CompileJava’ task does. But the original author deleted the ‘.gradle’ directory, which is where task outputs get persisted.