miranda

speed up your build with gradle

By breskeby | March 12, 2010

In my last post, I explained how to add aspectj support to gradle. Some tasks (like the shown iajc task) in complex projects take a lot of time, even though nothing has changed (e.g. neither the sources, nor the dependencies, nor the compiler settings). In my opinion fast builds are a key player in CI environments. An (up to now) underestimated feature of gradle is the ability to support you to keep your build jobs fast by making your builds incremental.
To speed up your build jobs, gradle offers an easy way to check whether executing a task is really necessary. Lets speed up our aspectj project build by skipping the compileJava task if its up-to-date.

Lets take a look at the original aspectj compile task:

1
2
3
4
5
6
7
8
9
10
11
12
task compileJava(dependsOn: JavaPlugin.PROCESS_RESOURCES_TASK_NAME, overwrite: true) < < {
    ant.taskdef( resource:"org/aspectj/tools/ant/taskdefs/aspectjTaskdefs.properties", classpath: configurations.ajc.asPath)
    ant.iajc(source:sourceCompatibility, target:targetCompatibility, destDir:sourceSets.main.classesDir.absolutePath, maxmem:"512m", fork:"true",
        aspectPath:configurations.aspects.asPath, inpath:configurations.ajInpath.asPath, sourceRootCopyFilter:"**/.svn/*,**/*.java",classpath:configurations.compile.asPath){
       
        sourceroots{
            sourceSets.main.java.srcDirs.each{
                pathelement(location:it.absolutePath)
            }      
        }
    }
}

When could the task be skipped or not? Gradle differentiates between inputs and outputs of a task. The task must be executed if:

  • If the output was deleted, manipulated or whatever
  • the input files have changed (e.g. sources and classpaths)
  • an property the task relies on

In the the compileJava task above

  • the output directory (the task result) is the classes directory (sourceSets.main.classesDir)
  • the input files are the sourceSets.main.java and all classpathes (iajc, compile, aspectpath, inpath)
  • the properties the task relies on are the compiler properties sourceCompatibility and targetCompatibility

to mark the respective parts gradle adds the properties inputs and outputs to a task. Have a look at the refactored code snippet:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
task compileJava(dependsOn: JavaPlugin.PROCESS_RESOURCES_TASK_NAME,
                overwrite: true) {
   outputs.files sourceSets.main.classesDir
   inputs.files sourceSets.main.java.srcDirs, configurations.aspects, configurations.ajInpath, configurations.compile
   inputs.properties(["sourceCompatibility":sourceCompatibility, "targetCompatibility":targetCompatibility])

   doLast{
    ant.taskdef( resource:"org/aspectj/tools/ant/taskdefs/aspectjTaskdefs.properties", classpath: configurations.ajc.asPath)
    ant.iajc(source:sourceCompatibility, target:targetCompatibility, destDir:sourceSets.main.classesDir.absolutePath, maxmem:"512m", fork:"true",
        aspectPath:configurations.aspects.asPath, inpath:configurations.ajInpath.asPath, sourceRootCopyFilter:"**/.svn/*,**/*.java",classpath:configurations.compile.asPath){
        sourceroots{
            sourceSets.main.java.srcDirs.each{
                pathelement(location:it.absolutePath)
            }      
        }
    }  
   }
}

speed up our build was really easy, wasn’t it? The example in this post uses one of the latest gradle 0.9 snapshots available at http://snapshots.dist.codehaus.org/gradle/. As Hans mentioned at the mailing list (and I definitely agree to that) they are of good quality. For further informations about the mentioned feature have a look at the latest javadoc for the Task, TaskOutputs and TaskInputs interfaces. Unfortunately this feature isn’t yet explained in the gradle userguide.

Have a nice day and keep comments about my english skills under your hat. ;-)

regards,
René

4 Responses to “speed up your build with gradle”

  1. Tomek Says:
    June 8th, 2010 at 05:42

    Hello Rene,

    a very interesting post indeed! How come that this feature is not mentioned in the Gradle userguide? I wasn’t able to find any hint on this.

    Definitely one of the bright points of Gradle.

    Many thanks for describing it.


    Tomek

  2. Rene Says:
    June 8th, 2010 at 08:11

    Hi Tomek,
    indeed is this great gradle feature not yet mentioned in the gradle userguide. Hans pointed me to this feature during his gradle talk at the java user group stuttgart (jugs). I think we have to improve the gradle userguide very soon.
    regards,
    René

  3. Tomek Says:
    June 8th, 2010 at 10:46

    Rene, is it important that you have this “doLast”? I tried to do the similar thing and it works fine without “doLast”.

    ?


    Tomek

  4. Rene Says:
    June 8th, 2010 at 18:03

    Hi,
    if you run the task without doLast{} the block is executed during the task configuration phase and not during the execution phase. This may work in such a simple example, but the task action should be executed only in the execution phase (not sure that execution phase is the correct phrase here)

    regards,
    René

Comments