2

How do you add a source set to a Java project in gradle 2.1?

I've read the docs on the Java Plugin and SourceSetOutput and a few other SO threads and I'm still struggling to figure out how it works.

I created a simple build script to test my understanding. Based on Section 23.7.2, example 23.5 of the User Guide, it appears I can create a sourceSet by doing:

sourceSets {
   generated
}

In section 23.4. Project layout seems to imply that this all I need to do because my source set follows the gradle convention. Code to be included in the source set is in src/generated/java/packagename. and will be automatically added to the classpath. Based on the symbol not found errors I'm getting from code that uses code defined in the generated source set, I assume that this incorrect and something else needs to be done. What do I need to do?

Here's my setup:

build.gradle

apply plugin: 'java'
apply plugin: 'application'

mainClassName = "tester.Test"

sourceSets {
    generated
}

File structure

tester/
├── build
│   ├── classes
│   │   └── main
│   ├── dependency-cache
│   └── tmp
│       └── compileJava
├── build.gradle
└── src
    ├── generated
    │   └── java
    │       └── tester
    │           └── Boom.java
    └── main
        └── java
            └── tester
                └── Test.java

Boom.java

package tester;

class Boom {
   String sound;

   public Boom (String s){
      sound = s;
   }
}

Test.java

package tester;

class Test {
   public static void main(String[] args) {
      Boom b = new Boom("KABOOM");

      System.out.println("I've run");
      System.out.println(b.sound);
   }
}
Opal
  • 81,889
  • 28
  • 189
  • 210
Jeffrey Guenther
  • 871
  • 10
  • 27

1 Answers1

1

You need to modify build.gradle in the following way:

sourceSets {
    generated
    main {
        compileClasspath += generated.output  // adds the sourceSet to the compileClassPath
        runtimeClasspath += generated.output  // adds the sourceSet to the runtimeClasspath
    }
}

project.run.classpath += sourceSets.generated.output //add the sourceSet to project class path

Remember that adding new source set is something different from having compiled source set in the classpath.

The line below the source sets is necessary for run task to work.

Jeffrey Guenther
  • 871
  • 10
  • 27
Opal
  • 81,889
  • 28
  • 189
  • 210
  • Thanks! This works for `gradle build`, however, when I try `gradle run` it gives me a `NoClassDefFoundError`. – Jeffrey Guenther Oct 06 '14 at 19:52
  • Hmm.. Indeed. I've also tested it with `run` but unfortunately without `clean`. Will have a look. – Opal Oct 06 '14 at 19:53
  • What I learned: Conceptually, sourceSets are boxes around collections of code. Even though you are using the java plugin, you'll still need to tell gradle how to use the information. Using a source set allows you to compile/test collections of your code separately. To use it in your project, you need to tell gradle how to use it. See the answer above for one example. Thanks @Opal! – Jeffrey Guenther Oct 06 '14 at 20:23
  • 1
    Yes, but mind the fact that not all runtime classpaths are modifiable - some of them can't be changed. Also gradle comes with some reasonable default, if You do something beyond the default usage You need to *tell* gradle about it. – Opal Oct 06 '14 at 20:26
  • Good points. Do you know where I can find out the details of what `Project` includes on the classPath? Since we're talking about, if I added tests, would I need to add the "generated" source set to the the test source set's path too? – Jeffrey Guenther Oct 06 '14 at 20:39
  • It's not the `project` that owns the classpath. In this case `run` task has the classpath. See here: https://github.com/gradle/gradle/blob/ccddc438ce09293d84030ebe31668d739c8a228a/subprojects/plugins/src/main/groovy/org/gradle/api/plugins/ApplicationPlugin.groovy. I guess `generated` source also may be added to tests. – Opal Oct 08 '14 at 14:44