Not everybody knows that you can specify for some ant targets to run only when some set of files was updated. It is particullary useful when working with GWT or Ivy.
In my GWT projects I usually have tasks like run-shell (which runs a hosted-mode browser) and compile-gwt (which runs the GWT compiler). The run-shell task depends on the compile-gwt task, but this would cause my GWT code to be recompiled every time I run the hosted browser. You may ask - why would you even rerun GWT shell, if you didn’t modify any of the GWT source files? The answer is quite simple - sometimes you don’t make any changes on the client, but only on the server-side and wan’t to see how these changes affect the client. Or maybe you just don’t want to recompile your GWT code every time you need to create the .war file and deploy your application or run ivy:retrieve everytime you run your build script. Anyway, I find this trick pretty usefull.
So how does the magic hapen? The whole trick is possible thanks to Ant’s uptodate core task. Below is the snippet from the example build.xml file:
<uptodate property="gwtBuild.notRequired"
targetfile=".gwtBuild">
<srcfiles dir="src"/>
</uptodate>
Uptodate task sets Ant property (here called “gwtBuild.notRequired”) when targetfile is newer (more up-to-date) than any of the files in the srcfiles fileset. Here I’m comparing it to the all directory contents, but srcfiles is a normal ant fileset so you can always use include and exclude tasks within. You can also use mapper subtask instead of targetfile for more complicated use cases.
So now that we know how the magic is done, it’s time to put it to a good use:
<target name="compile-gwt" unless="gwtBuild.notRequired">
<!-- invoke the GWT compiler here -->
<touch file=".gwtBuild"/>
</target>
The touch target will create .gwtBuild file if it doesn’t exist or update it’s last modified time otherwise. It should be invoked after the compilation succeeds, bacause if it wasn’t, in case of compilation failure the target would not be executed again unless any of the source files was modified. The “compile-gwt” target will execute only if the gwtBuild.notRequired property is not set thanks to the “unless” attribute.
Now for the finishing touch we need to delete the flag file in our clean task:
<target name="clean">
<!-- Delete the flag file for compile-gwt -->
<delete file=".gwtBuild"/>
<!-- Delete other files and directories -->
</target>
To illustrate usage of this technique I’m attaching to this post a simple GWT project with an Ant script. The project was tested on Windows with GWT 1.5M1 and GWT 1.4.61. To run it simply change the gwt.home property in build.properties file to point to your GWT installation directory.
Click here to download sample project
Hope you’ll find this tip usefull:)
Psyho