How to write a simple JavaCompile task?


(Todd Gerspacher) #1

The following is located on the last line of the third paragraph in section “7.1 The Java Plugin”:

“In fact, because support for Java projects is implemented as a plugin, you don’t have to use the plugin at all to build a Java project, if you don’t want to.”

Can someone provide me an example of what this would look like? That is, take a simple HelloWorld project that uses the Java plugin, comment out the line that applies the plugin, and write a task for compiling the code.

The following is what I came up with, but there’s still something wrong with it. I’m not exactly sure what it is. It also seems a little verbose to me, but Gradle complains if you don’t specify things like source and target compatibility.

task compile(type: JavaCompile) {
 source = fileTree(dir: 'src', include: '**/*.java')
 destinationDir = file('build/classes/main')
 sourceCompatibility = '1.7'
 targetCompatibility = '1.7'
 dependencyCacheDir = ???
 classpath = files('build/classes/main')
}

I’m really confused as to what I should set the dependencyCacheDir property to be. It’s a simple Java file that doesn’t really have dependencies.


(René Groeschke) #2

The default value used by the java-base / java plugin for that value is “${buildDir}/dependency-cache”. This dependencyCacheDir property is used when using ants “depend” task. have a look at https://ant.apache.org/manual/Tasks/depend.html for details

cheers, René


(Todd Gerspacher) #3

I set the dependencyCacheDir property to the value you suggested. For those interested, here’s what that looks like:

dependencyCacheDir = file("${buildDir}/dependency-cache")

After I made this change, I was able to compile my Java file. Thanks.


(Todd Gerspacher) #4

Is there a way to have the compiled class written to the same folder that the java source file is?

I tried the following…

task javac(type: JavaCompile) {
 source = fileTree(dir: '.', include: '*/*.java')
   classpath = files('.')
 destinationDir = file('.')
 dependencyCacheDir = file('.')
   sourceCompatibility = '1.7'
 targetCompatibility = '1.7'
}

…but it throws an IOException stating “The process cannot access the file because another process has locked a portion of the file.”


(Luke Daley) #5

You can’t have tasks use the entire project directory as either input or output. It’s a bad idea as it completely defeats incremental building.

You should store your inputs (source) and outputs (class files) in separate places. If you need to ship them together then aggregate them as a later step.


(Todd Gerspacher) #6

Thanks for answering my question Luke. I can narrow the task’s input to just the Java file with the following.

task javac(type: JavaCompile) {
   // ...
     classpath = files('HelloWorld.java')
}

Unfortunately, I can’t seem to narrow the task’s output to just the class file. I tried the following.

task javac(type: JavaCompile) {
   // ...
     destinationDir = file('.')
   dependencyCacheDir = file('.')
     outputs.file(file('HelloWorld.class'))
}

But it still shows the parent directory in the list of output files for the task. When Gradle takes a snapshot of the inputs, it puts a lock on the HelloWorld.java. This in turn causes the IOException to occur when it tries to take a snapshot of the outputs.

I did some more experimenting just to see how close to my goal I could get. This is what I came up with.

task javac(type: JavaCompile) {
   // ...
     classpath = files('bin')
   destinationDir = file('bin')
   dependencyCacheDir = file('bin')
     doLast {
      file('HelloWorld.class').bytes = file('./bin/HelloWorld.class').bytes
      file('./bin').deleteDir()
   }
}

The deleteDir returns true, which supposedly indicates the directory was successfully deleted. Yet the directory is still there.