TomDmitriev / gradle-bundle-plugin

Apache License 2.0
47 stars 24 forks source link

Using ${tstamp} variable in bundle instruction causes Gradle daemon to fail to compile due to corrupt jar #50

Closed gamerson closed 8 years ago

gamerson commented 8 years ago

Take this sample project uploaded here: https://github.com/gamerson/daemon-compiler-failure

This project has 2 simple bundles built using DM plugin. And "api" and "impl". When rebuilding the impl jar using "gradlew --daemon jar" you can see eventual failures in the gradle compileJava task just by re-running the same command with no change to the source files. Here is the error that is shown:

~/dev/my repos/daemon-compiler-failure/impl ../gradlew --daemon jar
:api:compileJava UP-TO-DATE
:api:processResources UP-TO-DATE
:api:classes UP-TO-DATE
:api:jar UP-TO-DATE
:impl:compileJava UP-TO-DATE
:impl:processResources UP-TO-DATE
:impl:classes UP-TO-DATE
:impl:jar UP-TO-DATE

BUILD SUCCESSFUL

Total time: 0.718 secs
~/dev/my repos/daemon-compiler-failure/impl ../gradlew --daemon jar
:api:compileJava UP-TO-DATE
:api:processResources UP-TO-DATE
:api:classes UP-TO-DATE
:api:jar
:impl:compileJava
/Users/greg/dev/my repos/daemon-compiler-failure/impl/src/main/java/org/gradle/impl/PersonImpl.java:3: error: cannot access Person
import org.gradle.api.Person;
                     ^
  bad class file: /Users/greg/dev/my repos/daemon-compiler-failure/api/build/libs/api-1.0.0.jar(org/gradle/api/Person.class)
    unable to access file: corrupted zip file
    Please remove or make sure it appears in the correct subdirectory of the classpath.
:impl:compileJava FAILED

FAILURE: Build failed with an exception.

* What went wrong:
Execution failed for task ':impl:compileJava'.
> Compilation failed; see the compiler error output for details.

* Try:
Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output.

BUILD FAILED

In the repo I linked to I have the full reproduce steps. The way to fix the error is to simply drop off the "${tstamp}" variable in the bundle instruction. I suppose that ${tstamp} variable expansion by bndlib is throwing off the manifest 'out-of-date' calculation someway. But of course the worst case scenario is that gradle just reruns the "api:jar" task when it doesn't need to. It should not be throwing the compilerJava task exception.

This never happens if you are not invoking with the daemon. It appears to be a daemon/caching problem that is triggered by the changing manifest hash inside of DM plugin.

Thoughts?

gamerson commented 8 years ago

There is a good chance that this issue will also be fixed with https://github.com/TomDmitriev/gradle-bundle-plugin/issues/51 I'll give it a try

TomDmitriev commented 8 years ago

Thanks for the demo! Compilation of impl module is triggered when api.jar is changed, which happens because META-INF/MANIFEST.MF inside api.jar is changed, which in turn happens due to the fact that tstamp is updated. That is the way Gradle works with or without this plugin, so this part is not surprising. The perplexing part is why compilation sometimes fails complaining about corrupted api.jar. I have checked that the file does exist and if the daemon is killed and started again :impl:compileJava becomes successful without re-writing api.jar, so its content does not seem to have anything to do with the problem. Without deeper and, I fear, quite-time consuming investigation I suggest as a work-around running compilation in a separate process, which seems to fix the issue, i. e.

subprojects {
    ...

    compileJava {
        options.fork = true
    }
}

(v0.8.1 is required)

gamerson commented 8 years ago

so even with fix in #51 applied it still happens but I can confirm that setting compiler.fork = true does fix the issue for me, so I can consider this one closed.