sourceSets.main.allSource not showing all the java source

I’m currently converting a number of Ant projects to Gradle, however I have run into an issue relating to the generation of Source artifacts to be uploaded to Artifactory.

In my build.gradle I have the following configuration:

sourceSets {
  main {
    java {
      srcDir 'base'
      srcDir 'general'
      srcDir 'serialization'
    }
    resources {
      srcDir 'base'
      include 'spring/**'
    }
  }
}

When I try and view the source using:

println "Sources : " + sourceSets.main.allSource.files

It does not display the source contained within ‘base’. If I remove srcDir ‘base’ from the resources it works fine, However I have resources contained in a subdirectory which I need to use.

If I have the following:

resources {
      srcDir 'base/spring/'
    }

The Java source is correctly returned, but the resource items are located in the wrong location (not in the spring directory).

What am I missing here? The compilation works perfectly and the resources are correctly located in my first example, just when I generate the Source jar file it is missing one of the source trees.

My Source jar creation task is:

task sourceJar(type: Jar, dependsOn: classes) {
  from sourceSets.main.allSource
}

You should be able to omit the ‘resources’ configuration closure entirely since your resources exist within a directory that is already defined as a java source directory.

There are two ways, you can grab the resources directly from the source set:

from sourceSets.main.resources.outputs

or (more correctly) grab the post-processed resources copied into the build/ dir.

from processResources.outputs

If I omit the resources configuration entirely, the resulting artifact does not contain the ‘spring’ folder at all. It only contains the packages containing the classes.

You are correct. It seems resource files will only incidentally be included if the exist in a package also containing java source. This may be a bug. Calling ‘sourceSets.main.allSource’ should (if I am interpreting the javadoc correctly) return both java source and resource files. It seems as though if you define a resources directory that exists in a java source directory it is getting confused. The following should properly return both the java source and resource files.

sourceSets.main.allJava.files + sourceSets.main.resources.files

I’ve tried putting in a dummy Java class to that folder but still no joy with the resource files being found and added to the compiled jar file. Also the

sourceSets.main.resources.files

always returns an empty set unless I explicitly set the

sourceSets {
    main {
        resources {
            srcDir.......
        }
    }
}

That should be expected. My thought was my example above should return all source (including java and resources) with the sourceset configuration you have in your original post. Is that not the case?

Actually, that is correct, the xml and java files are included as you described, however I actually think what is the issue is relating to the publishing task. I am using the maven-publish task to publish the artifact, but the resulting artifact jar doesn’t contain the resource files, only the class files. The publish task I am using is as follows:

publishing {
  publications {
    artifact(MavenPublication) {
     groupId 'com.something'
      artifactId "${project.artifactName}"
      from components.java
       artifact sourceJar {
                classifier "sources"
            }
      }
  }
  repositories {
.....
}
}

it seems that the components.java only includes explicitly listed resources.

I’ve created a git repo with an example. in the current state the gradle publishToMavenLocal does not include any resources, however when the commented lines are added they are included. https://bitbucket.org/fergusb/gradle-test/src

If you uncomment those lines and change your sourcesJar task to like below, does everything seem to come out correctly? Is the artifact that is being published to maven differ from the one Gradle places in your build directory?

task sourceJar(type: Jar, dependsOn: classes) {

from sourceSets.main.allJava.files + sourceSets.main.resources.files

}

That seems to have done it alright! Thanks for the assistance.

However, ‘should’ the publications task not include resources found in the Java srcDir anyway? Because as you mentioned earlier non-java files found in the java srcdirs are supposed to be included as resources.

I don’t think the issue was with publication. The reference to ‘components.java’ is really just the output of the ‘jar’ task, same as with ‘artifact sourceJar’. The necessary change was that to the ‘sourcesJar’ task. Like I mentioned before, I believe there may be some issue with the way Gradle handles source set resources when that directory falls within a previously configured java source directory.

This does in fact look like a bug in Gradle. In fact, there is a comment alluding to this in ‘DefaultSourceDirectorySet’.

// This implementation is broken. It does not consider include and exclude patterns

Essentially, what is happening is Gradle is filtering out what it sees as non-unique file sets when evaluating. However, it is only taking into account the ‘srcDir’ when doing so. In your case one spec includes a filter pattern and the other doesn’t. In fact, since this collection is stored in a ‘LinkedHashSet’ one would expect the resultant behavior to be non-deterministic. In this case, the spec with the filter pattern wins (happens to be first), resulting in your source jar including only those files matching the ‘spring/**’ pattern.