When/why does Gradle extract .class files from dependencies to build/classes/?

I’ve sometimes seen that Gradle extracts .class files from Java dependency JAR files into build/classes/. When and why does Gradle do this? I’ve not been able to find any pattern.

This causes trouble with our Checkstyle/FindBugs checks, and lately it seems like this gives us compilation errors because of name clashes, but only on a few machines.

I’d be surprised if it ever did, by itself. Can you provide a self-contained example? Which exact directory is affected (‘build/classes’, ‘build/classes/main’, etc.)?

It seems that this issue was caused by a .jar file with Java source files in it.

If you can provide a self-contained example, we’ll have a closer look.

Yes, David is right, I have experienced this as well.

It seems to be caused by Java compiler compiling sources across jars on the classpath. It can be reproduced if Gradle is set to use Ant’s java compiler (I think this was the default behavior before but now it’s not so it has to be configured explicitly):

apply plugin: 'java'
  repositories {
    mavenCentral()
}
  dependencies {
    compile 'org.apache.servicemix.bundles:org.apache.servicemix.bundles.opensaml:2.5.1_2'
}
  compileJava.options.useAnt = true
  task createDummyJavaSource << {
    File srcDir = sourceSets.main.java.srcDirs.iterator().next()
    srcDir.mkdirs()
          new File(srcDir, 'Foo.java').text = """
      import org.opensaml.saml2.core.Assertion;
      public class Foo { }
    """
}
  compileJava.dependsOn(createDummyJavaSource)

At the time it happened, we figured that the workaround is to set the ‘-sourcepath’ compiler argument:

compileJava.options.compilerArgs += ['-sourcepath', sourceSets.main.java.srcDirs.join(File.pathSeparator)]

Regards,

Detelin

I wouldn’t set the sources to be compiled as source path. Probably you are running into this javac behavior:

-implicit:{class,none} Controls the generation of class files for implicitly loaded source files. To automatically generate class files, use -implicit:class. To suppress class file generation, use -implicit:none. If this option is not specified, the default is to automatically generate class files. In this case, the compiler will issue a warning if any such class files are generated when also doing annotation processing. The warning will not be issued if this option is set explicitly. See Searching For Types.

In that case, I’d try to set ‘implicit:none’.

You are right, this is it. Using ‘compileJava.options.compilerArgs << ‘-implicit:none’’ fixes this. I’m not sure why they chose the default to be generating class files, for Gradle it’s probably a good idea to change it, otherwise people would be getting some unwanted classes in their jars, which is hard to notice.

By the way, this issue does not seem to be triggered by setting ‘useAnt=true’ as I originally thought, but by referencing (importing) classes from jars that contain sources.

Regards,

Detelin