Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to compile a single java file with gradle?

Tags:

java

gradle

(UPDATED: Thanks to comments from Peter N below.)

I have a java package with several classes and therefore files within it. However I only want to compile one of those files initially so that I can then use it to update the other classes in the package. It's a factory for the other classes and as a result is dependent on them - ie. it has references to them.

I've been attempting to use a JavaCompile gradle task to do this. As a result I've read the documentation for JavaCompile and attempted to search for examples but seems there is very little out there. I've even posted on the gradle forums, but slow going so far.

I'm able to do what is required readily with an ant script using the ant javac task. But I'd like to do it in gradle (and without using the ant.javac method - if I have to do that I'll just use ant).

I've created an example case with just two source files for two classes in the one package.

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.

The ant script is 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 (or JavaCompile task) can not find ClassOne. It's as though the sourcedir is not pointing where it should - and indeed as though I was just running javac on the command line. 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 how do I achieve an ant javac equivalent in gradle?

ant javac seems to have the smarts to go and compile all the other related classes, but I guess for gradle JavaCompile I will need to set up a sourceSet to do that.. not sure..

Thanks!

like image 652
I Stevenson Avatar asked Oct 15 '13 22:10

I Stevenson


People also ask

Does Gradle build compile?

By default, Gradle will compile Java code to the language level of the JVM running Gradle. With the usage of Java toolchains, you can break that link by making sure a given Java version, defined by the build, is used for compilation, execution and documentation.


1 Answers

Thanks to the discussion with @PeterNiederwieser on the original post in the comments, I'll provide the answer here for completeness.

To have gradle JavaCompile function in a manner very similar to the ant javac, you need to provide the sourcepath compiler option via the options.compilerArgs property. Therefore, the gradle script that now works is as follows:

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
}

compileOne.options.compilerArgs = ["-sourcepath", "$projectDir/src/main/java"]

Note specifically the last line (the only difference) which allows all to work. The result of which is that it will actually compile both ClassOne and ClassTwo at build time - rather than only attempting the single explicit file you specified. Any other classes (that are not required) remain uncompiled - as confirmed by looking in the build directory.

Thanks Peter!

like image 87
I Stevenson Avatar answered Sep 16 '22 19:09

I Stevenson