How to compile a single java file?


(I Stevenson) #1

I have a java project with many source files, however one of the files needs to be compiled first to then generate other source files for the full compilation.

Historically a simple ant javac task has done the trick. But attempting to do the same with gradle is proving troublesome. So as an example I’ve created a simple example with just two files.

Both files are in a package called some.pkg and we therefore have the following directory structure:

.\build.gradle .\src\main\java\some\pkg\ClassOne.java .\src\main\java\some\pkg\ClassTwo.java

ClassOne:

package some.pkg;
  import some.pkg.*;
  public class ClassOne {
 public void doStuff() {
 }
}

ClassTwo

package some.pkg;
  import some.pkg.*;
  public class ClassTwo {
 public void ClassTwo() {
  ClassOne cone = new ClassOne();
  cone.doStuff();
 }
}

As you can see, ClassTwo (our class we want to compile standalone) depends on ClassOne.

Normally (ant aside) it would be completely fine to run javac from the command line as follows:

.\src\main\java> javac some\pkg\ClassOne.java

And in ant, it’s a simple case of:

<project>
 <property name="build.dir"
value="build"/>
 <property name="lib.dir"
value="lib"/>
 <property name="src.dir"
value="src/main/java"/>
   <target name="generate" >
  <mkdir dir="${build.dir}"/>
    <javac source="1.6" target="1.6" srcdir="${src.dir}" destdir="${build.dir}"
       debug="true" includeantruntime="false"
      includes="some/pkg/ClassTwo.java">
  </javac>
 </target>
</project>

But in gradle, I keep having an issue where javac can not find ClassOne. It’s as though the sourcedir is not pointing where it should. I was thinking the gradle ‘JavaCompile’ task’s ‘source’ property was working like the ant ‘srcdir’ property, but that appears to not be the case. So here is the gradle script I’m currently trying:

apply plugin: 'java'
  task compileOne (type: JavaCompile) {
 source = sourceSets.main.java.srcDirs
 include 'some/pkg/ClassTwo.java'
 classpath = sourceSets.main.compileClasspath
 destinationDir = sourceSets.main.output.classesDir
}

But it results in:

C:\test\>gradle generate
:generate
C:\test\src\main\java\some\pkg\ClassTwo.java:7: cannot find symbol
symbol
: class ClassOne
location: class some.pkg.ClassTwo
                ClassOne cone = new ClassOne();
                ^
C:\test\src\main\java\some\pkg\ClassTwo.java:7: cannot find symbol
symbol
: class ClassOne
location: class some.pkg.ClassTwo
                ClassOne cone = new ClassOne();
                                    ^
2 errors
:generate FAILED

So do I achieve an ant javac equivalent in gradle? (Obviously I’m attempting to avoid doing ant.javac()…)

Thank you!


(Attila Kelemen) #2

What you could do is to put that single file into a separate source set and let the main source set depend on it.

sourceSets {
    preBuildSources
    main {
        java {
            srcDir 'build/generated-src/java'
        }
          compileClasspath += preBuildSources.output
        runtimeClasspath += preBuildSources.output
    }
}
  // Assuming you have a generateSources task.
compileJava.dependsOn generateSources
generateSources.dependsOn compilePreBuildSourcesJava

(I Stevenson) #3

Hi Attila,

Thank you for your reply. However I’m not sure how it solves the issue.

I may be missing something with how you’ve described it, and i may have confused the issue by mentioning the source generation. However the key issues is that in the example - not around source generation.

If I understand what you’ve said, you’re essentially saying I should move ClassTwo.java into a different directory from ClassOne.java. But I need to keep these guys in the same package - and therefore directory. Have I missed something?


(Attila Kelemen) #4

Given your output and my example, you should have ClassTwo.java in ‘src/preBuildSources/java/some/pkg/ClassTwo.java’. Notice that “main” have been replaced with “preBuildSources”. Every other file should be where it was. Notice that ClassTwo is still in the same package where it was.

I just mentioned code generation for the sake of completeness.


(Attila Kelemen) #5

Also, you may have to adjust the ‘compileClasspath’ and ‘runtimeClasspath’ of ‘preBuildSources’. For example:

sourceSets {
    preBuildSources {
        compileClasspath += configurations.compile
        runtimeClasspath += configurations.runtime
    }
}

(I Stevenson) #6

All good, all sorted over on stackoverflow: http://stackoverflow.com/questions/19391872/how-to-compile-a-single-java-file-with-gradle

Cheers all.