Skip to content

Ant

Apache Ant is a build tool. It lets software developers automate many of the tedious things that happen in software projects: cleaning, building, deploying, running unit tests, and more. Its extremely flexible, and offers a way to guarantee that a project can be built outside of an IDE.

This page details some of the tricks I've learned using Ant.

Build Script Properties

Its normal to need parameters in a build script. Common things that are parameterized are: server names, build numbers, filenames, and options to various external commands. So what mechanism exists to deal with that? Ant has one, called the <property> tag. Here's an example:

<project name="myProject" default="usage">
        <property file="myProject.props" />
....

This is the first two lines of an ant build script. The <property> tag tells ant to look in a file called myProject.props to find the properties. Since no directory name is specified, ant will look for the file in the same directory as the build script.

The myProject.props file should contain key/value pairs like this:

version=1.0.1
appname=Daily Reminders
uri=/reminder
sourceDir=/home/chris/myproject

You can use an equals sign or a colon as the separator, and there can be whitespace or not (it will be ignored). The syntax allowed in property files can be foundhere.

To use the properties in a build script, follow this syntax:

<target name="deploy-app" description="Deploys the app">
    <antcall target="deploy">
        <param name="appname" value="${appname}" />
        <param name="uri" value="${uri}" />
    </antcall>
</target>

The values for appname and uri will be substituted at runtime for the expressions inside quotes (${appname} and ${uri}). Use the same syntax inside the deploy target to use the parameters. Here is a nice way to guarantee the parameters aren't blank...

<target name="deploy" description="Deploys the app">
    <fail unless="appname" message="Param 'appname' not given in deploy target." />
    <fail unless="uri" message="Param 'uri' not given in deploy target." />
    ...etc...
</target>

Foreign Language Characters in Filenames

I received multiple warnings/errors in a build process because some of the filenames contained foreign language characters (from my JVM's perspective). The JVM uses the host machine's settings to determine its locale at runtime, and it makes assumptions about filenames from there. To overcome those warnings, I had to override the default JVM encoding settings in my ant script. Here is how I did that:

<javac encoding="CP1252" srcdir="/test/java" destdir="/test/classes"></javac>

Notice the encoding parameter. Pretty simple. 8-) Your settings might be different.

Using LINT

Lint was added to Java SE 1.5, and can be enable in ANT by adding a simple parameter to the javac parameter. Extending the above example:

<javac encoding="CP1252" srcdir="/test/java" destdir="/test/classes">
    <compilerarg value="-Xlint:all,-path"/>
</javac>

There are many options for lint. For a summary, type the following at the command line:

javac -X

Capturing Build Output to a File

I wanted to capture the output of my build script for analysis purposes, but there isn't a simple inline way to do that. Fortunately, ant has the <record> tag...

<target name="autodeploy" description="Deploy & capture output">
    <record name="myapp_build_log.txt" action="start" append="false" />
    <echo message="Performing the build..." />
    <antcall target="deploy-all" />
    <record name="buildlog.txt" action="stop" />
</target>

I call the above target when I want to do an automated deployment (via a shell script) and capture its output. Notice the first <record> tag contains an action=start attribute. That turns the recorder on. The append=false attribute causes the file to be overwritten if it already exists. The actual work is done by the <antcall> element, which has no awareness that its output is being recorded. The final <record> element turns the recording off and closes the file. After this tag runs, I have a file that I can email to someone.

Sending Build Output as an Email

I like to send emails as part of a Continuous Integration process. But I don't always want to send email when I deploy my application. So I write a separate ant tag to send email, and I assume the build log is in the proper place. I don't worry about checking if the file exists...its OK to get an empty email if things foul up.

<target name="send-email" description="Send email">
    <mail subject="Build Report"
        from="root@192.168.1.84"
        tolist="${email.list.csv}"
        files="myapp_build_log.txt"
        encoding="plain">
        <message>Output of the deploy process follows:
        </message>
    </mail>
</target>

The <mail> tag contains everything necessary for sending email: a to and a from address, a subject, a message, and the name of a file to include after the message. Assuming email works from your host, simply calling this tag will send the build log in the body of an email to everyone whose email addresses you've specified in the email.list.csv property.

Email addresses should be entered like this in the properties file:

  email.list.csv=me@myhost.com,you@myhost.com,someone_else@myhost.com