Ant 1.6 is a step forward

After using Ant for many years and complaining how it’s slowly being screwed up by introduction of control structures and other such rubbish I’m pleased with the release of 1.6. 1.6 contains some much needed features for enterprise use of Ant. The most notable of these is the introduction of a macro specification via the macrodef element, and finally the inclusion of a decent import facility. These two now make it possible to create reusable sections of XML and in the case of the import have a target “overridden” by a target of the same name in the master build file.

Hooray I say. Now it’s going to be a matter of going through a bunch of my old build.xml files and extracting useful macrodef candidates (I was using antcall for this).

As an example, here are some build files that I’m currently working with.

build.xml

<project name="skillsmatrix" default="compile" basedir=".">
<property name="props.POI_ROOT" value="d:/var/jakarta-poi" />
<property name="poi.root" value="${props.POI_ROOT}" />
<property name="poi.jar" location="${poi.root}/build/jakarta-poi-1.5.1.jar" />
<import file="general-macros.xml" optional="false" />
<import file="standard-targets.xml" optional="false" />
<application-property-setup root="${basedir}" name="skillsmatrix" />
<application-classpath classes="${app.classes}" >
<jar-files>
<pathelement location="${poi.jar}" />
</jar-files>
</application-classpath>
</project>

And the macros live in the file general-macros.xml, an extract looks like this:

<project name="general-macros" >
<macrodef name="application-compile">
<attribute name="srcdir" default="${app.src}" />
<attribute name="destdir" default="${app.classes}" />
<attribute name="classpathref" />
<attribute name="excludes" default="" />
<sequential>
<javac
srcdir="@{srcdir}"
destdir="@{destdir}"
includeAntRuntime="no"
excludes="@{excludes}"
debug="on"
optimize="on" >
<classpath refid="@{classpathref}" />
</javac>
</sequential>
</macrodef>
<macrodef name="application-classpath" >
<attribute name="classes" />
<element name="jar-files" />
<sequential>
<path id="app.classpath">
<pathelement location="@{classes}" />
<jar-files />
</path>
</sequential>
</macrodef>
</project>

And finally the targets. Notice how the import files have a fully structured project node around them. Just like a normal build file.

<project name="standard-targets" >
<target name="init">
<tstamp />
<echo message="Checking environment" />
<echo message="     OS = ${os.name}" />
<echo message="   Home = ${user.home}" />
<echo message="Project = ${app.name}" />
<echo message="Basedir = ${app.root}" />
<echo message=" srcdir = ${app.src}" />
<property name="tmp" refid="app.classpath" />
<echo message="CLASSPTH= ${tmp}" />
</target>
<target name="mkdir" >
<mkdir dir="${app.classes}" />
<mkdir dir="${app.jdoc}" />
</target>
<target name="clean">
<delete dir="${app.classes}" />
<delete dir="${app.jdoc}"/>
<delete file="${app.jar}" />
</target>
<target name="compile" depends="mkdir" >
<application-compile classpathref="app.classpath" />
</target>
</project>

Notice how in the target include file, the use of the macro defined in the other file. As this is my first pass at getting these structures to work, I’m sure I’ll find better ways as time goes on, but the signs are good !

Advertisements