Quick tips to speed up your Ant build

For those of you using Ant to build your Flex applications, here is a quick tip to speed it all up. If you have a build script that builds more than one SWF or SWC, instead of building everything everytime you can use Ant’s uptodate task to have the script skip running targets whose sources haven’t changed.

Let’s jump directly to an example of how this can be done. This is a snipplet from an Ant build file:

<target name="init">
  <uptodate property="uptodate.main" targetfile="path/to/swf">
    <srcfiles dir="path/to/src">
      <include name="**/*.as"/>
      <include name="**/*.mxml"/>
    </srcfiles>
  </uptodate>
</target>

<target name="build" depends="init" unless="uptodate.main">
  <mxmlc .../>
</target>

What happens here is that when the build target is run Ant will first run init since it’s a dependency of build. The init target will set the uptodate.main property if none of the source files in the source directory has a newer modified date than the target file (e.g. a SWF). The name of the property can be anything, but it is probably a good idea to have some kind of prefix if you have more than one of these.

Ant then looks at the build target again and sees that it should run unless the uptodate.main property is set. This means that if the ource files hadn’t changed since the target file (e.g. the SWF) was created the target will not run.

As an aside, please not that it can be important to understand that Ant doesn’t look to see if the uptodate.main property is true or false, but whether or not it is set at all. The value of the property is in fact not important. The uptodate task will set the property to the value “true” if the files are up to date, but if they are not the property will not be set at all. Ant is like that and it can sometimes be confusing.

If you have a build script that builds more than one SWF or SWC (for example a main SWF and a number of RSL:s), this can really speed up things. I hate looking at the build process and seeing that things that doesn’t need to be recompiled getting recompiled anyway because it’s a dependency of another thing. An alternative is of course to build each target manually, but the whole point of using build scripts is that all you have to do is say “build”, “deploy”, etc. and get it done. I don’t want to keep things in my head, I just want it do be done, and the quicker the better.

I hope this will save you a few seconds each day.

6 Responses to “Quick tips to speed up your Ant build”

  1. Maz Says:

    That’s a great tip indeed !

    Do you know the “incremental” command-line argument of mxmlc ? It is supposed to do quite the same job, but it never works for me…

    Thanks for sharing

    {Maz}

  2. Theo Says:

    The incremental flag is for recompiling only that which has changed, but I don’t think it skips the compilation if nothing has changed, at least not when I have tried. I think the problem with incremental is that if class A has changed it still compiles the classes that class A uses, and then the classes that those classes use and so on… so in reality the benefit quickly approaches zero (but I could be wrong, I’m not sure if it’s actually that dumb).

  3. Ricki Says:

    Hi This looks great! Im just in the process of putting together an Ant script for our main project. I compiles 9 different modules into one AIR app, so what you are suggesting here could really save me some time.

    Im just not quite sure how to implement this. What if I have 9 swf’s, am I suppose to write something resembling the init target for each of these? I have already put all of the compile action into a macro to produce a less cluttered script, how would this work for multiple swf’s (which is the whole point: )

    Thanks again for trying to save other peoples time :) a noble course.

  4. Theo Says:

    This tip works for telling Ant whether or not to run a target, so to use it to conditionally compile N separate SWFs you need N+1 targets (apart from the init target that contains the uptodate-statements); one for each file and one that depends on all the others (so you can type “ant compile” and compile the lot). You also need N uptodate-statements in the init target, and make sure the init target runs first:

    <target name="init">
      <uptodate property="uptodate.someswf" targetfile="path/to/some.swf">
        <srcfiles dir="path/to/src">
          ...
        </srcfiles>
      </uptodate>
      <uptodate property="uptodate.someotherswf" targetfile="path/to/another.swf">
        <srcfiles dir="path/to/some/other/src">
          ...
        </srcfiles>
      </uptodate>
      ...
    </target>

    <target name="build" depends="init, compile1, compile2, compile3"/>

    <target name="compile1" unless="uptodate.someswf"> <mxmlc .../> </target>

    <target name="compile2" unless="uptodate.someotherswf"> <mxmlc .../> </target>

    ...

  5. Ricki Says:

    Hi Theo That is great, I’ll surly include that n my compile macro somehow.

    Thanks for elaborating:)

  6. Carl van Tonder Says:

    Thanks for the tip — I’m using both incremental and uptodate, and build times have gone down from a regular 4 minutes to 17 seconds (where only a single module has changed). Thanks!

Leave a Reply