Anatomy of a Build File

Ant projects all revolve around one or more build files. By default, Ant looks for a build file named build.xml. Because Ant files are XML documents, they start with an XML declaration, as all valid XML documents must:

<?xml version="1.0" ?>
        .
        .
        .

Tip

For the complete XML 1.0 syntax, look at http://www.w3.org/TR/REC-xml/. XML 1.1 is out now as well, but Ant build files are based on XML 1.0, and the difference between these versions is small anyway, centering mostly on the manner in which certain Unicode characters are supported.

Projects

Every Ant build file contains exactly one project. You set up an Ant project in a build file with the project element, which is the document element—i.e., the element that contains all other elements:

<?xml version="1.0" ?>
<project>
        .
        .
        .
</project>

As Ant build files are just XML, you'll need to know which attributes are allowed on the top-level project element.

Tip

You'll also want to know about the elements that can be nested within project. Those are dealt with throughout the rest of this chapter and in Chapter 2.

The three allowed attributes for the project element are shown in Table 1-1.

Table 1-1. The project element's supported attributes

Attribute

Description

Required

name

Defines the project name

No

default

The target to invoke if no target is explicitly specified

Yes

basedir

The base directory from which all relative paths are resolved

No

Note that the default attribute is required. This attribute points to the Ant target that you want run by default; in other words, this controls what happens when you type ant at the command prompt, without any other special instructions. In the following case, the default target is main:

<?xml version="1.0" ?>
<project default="main">
        .
        .
        .
</project>

Targets

An Ant target is a group of tasks that you want Ant to perform. These tasks are grouped together into one easily remembered unit, which is the target. For example, you might have a target deploy which opens an FTP connection to a remote server, uploads various files, and closes the connection. Though multiple tasks may be involved (opening the connection, performing an upload, closing the connection, and perhaps checking for error messages), it's easiest to think of this as one unit of work. Considering this as a single target makes it reusable and easily accessed from various portions of your build file.

Another example might be a target named init that initializes a build by deleting output directories and recreating them so they'll be empty, as well as copying over license files that should be a part of every build. You might use a target named compile to compile dozens of source files across various directories and store the results in various output directories. In all these cases, the target handles piecing together various individual tasks.

Ant build files are made up of targets like these. For example, to create the main target, you use the target element, along with the name attribute:

<?xml version="1.0" ?>
<project default="main">

    <target name="main">
        .
        .
        .
    </target>
  
</project>

You can see the possible attributes for the target element in Table 1-2.

Table 1-2. The target element's attributes

Attribute

Description

Required

name

Defines the target name

Yes

depends

Comma-separated list of targets to execute before this target

No

if

Name of a property needed to run this task

No

unless

Name of a property that can not be set before running this task

No

description

Description of this target's purpose

No

Tasks

You populate an Ant target with tasks; a task is an XML element that Ant can execute to make something happen. For example, the echo task echoes text messages to the console:

<?xml version="1.0" ?>
<project default="main">

    <target name="main">
        <echo>
               Building the .jar file.
        </echo>
    </target>
  
</project>

To create an Ant target, you place Ant tasks like echo inside a target element; in this case, the main target only has one task, but you can include hundreds.

Built-in tasks

As you'd expect, Ant comes with a large number of built-in tasks, and you can see them all in Table 1-3 (many of these tasks may contain subelements).

Tip

In cases where a task is listed and followed by another task name in brackets (as in apply [execon]), the first task is the current name you should use; the second task is an older name that performs similar functionality but is now deprecated. Always use the task not in brackets to ensure your code is current.

Table 1-3. Core Ant tasks

Task name

Description

ant

Executes Ant

antcall

Executes a target from the current build file

antstructure

From a given build file, creates a DTD reflecting all of the tasks Ant currently knows about

apply [execon]

Invokes a native executable

available

Sets a Boolean value in a property according to the availability of desired resource

basename

Sets a property to the last element of a specified path in an effort to determine a file's name without directory structure

buildnumber

Manages build numbers

bunzip2

Expands GZip or BZip2 archives

bzip2

Packs GZip or BZip2 archives

checksum

Creates checksums for one or more files

chmod

Modifies file permissions on Unix

concat

Concatenates multiple files

condition

Checks the result of a condition and sets the result to in a property

copy [copydir, copyfile]

Copies files

cvs

Interacts with a CVS repository

cvschangelog

Converts a series of CVS change logs into an XML report

cvspass

Adds entries to a .cvspass file

cvstagdiff

Creates an XML report highlighting the differences between tags

cvsversion

Finds the CVS software version

defaultexcludes

Modifies the list of default exclude patterns, affecting which files are automatically excluded from processing by file-related tasks

delete [deltree]

Delete files and folders

dependset

Deletes target files that are older than new source files

dirname

Assigns a file's directory path to a property

ear

Extends the jar task to support handling files for an Enterprise Application archive (EAR)

echo

Echoes text to System.out or to a file

exec

Invokes a native executable

fail

Halts and exits a build by throwing a BuildException

filter

Sets a token filter that can be used by filter-related tasks such as copy

fixcrlf

Adds or remove tabs, carriage returns, linefeeds, and EOF characters from a set of files

genkey

Adds a new key to a given keystore

get

Retrieves files using FTP, HTTP, and more from a URL

gunzip

Unpacks a GZip file

gzip

Packs a GZip file

import

Allows the use of other Ant files

input

Displays a message and reads a line of input from the console, allowing for user input during the build process

jar

Creates a JAR archive similar to Java's jar command

java

Executes the Java interpreter to run a class or application

javac

Compiles the specified source file(s)

javadoc [javadoc2]

Invokes the javadoc tool to create documentation

loadfile

Sets a property file to the entire contents of a text file

loadproperties

Loans an entire property file into Ant properties

macrodef

Defines a new task as a macro built-up upon other tasks

mail

Sends SMTP mail messages

manifest

Creates an archive's manifest file

mkdir

Makes a new directory

move [rename]

Moves a file to another directory

parallel

Contains other Ant tasks that can be run simultaneously by multiple Java threads

patch

Uses the patch command (assuming it is on the path) to apply diff files to a source file (or files)

pathconvert

Converts paths between platforms

presetdef

Defines a new task based on an existing task with certain options preset as defaults

property

Sets one or more properties to new values

record

Runs a listener that records the logging output of the build process to a file

replace

Replaces a string with another in all files in a directory

rmic

Invokes the rmic compiler

sequential

A container task that can contain other Ant tasks and run them in sequence

signjar

Uses the JarSigner to securely sign ZIP and JAR archives

sleep

Suspends execution for a specified period of time

sql

Runs SQL statements against a database

subant

Runs Ant within all subdirectories of the project directory

sync

Synchronizes two directory trees

tar

Makes a new TAR archive

taskdef

Creates a new task definition and adds it to the current project

tempfile

Sets a temporary filename to an Ant property

tstamp

Sets time-based properties to the current time

typedef

Creates a new task or data type for use in the current project

unjar

Unpacks a JAR file

untar

Unpacks a TAR file

unwar

Unpacks a WAR file

unzip

Unpacks a ZIP file

uptodate

Sets a property value to true if a given target file is newer than a set of source files

waitfor

Halts a build and continues when specified conditions are met

war

Creates WAR archive files (an extension of the jar task)

whichresource

Locates a class or resource, either on the current class path or the system class path

xmlproperty

Loads Ant properties from an XML property file

xslt [style]

Transforms a set of documents via XSLT

zip

Creates and packs a new ZIP archive

Optional tasks

Besides these built-in tasks, called the core tasks, Ant supports many optional tasks, which you can see in Table 1-4. These tasks may require the support of additional JAR files, which you load into the Ant lib directory. For example, ftp uploads files to remote servers; you need to place the JAR files jakarta-oro.jar and commons-net.jar in your Ant lib directory to use the task. Another optional task is csc, which compiles Microsoft C# code:

<csc optimize="true" debug="false" 
    warnLevel="4"   
    unsafe="false" targetType="exe" incremental="false" 
    mainClass = "Main" destFile="app.exe" > 
    <src dir="src" includes="*.cs" /> 
    <reference file="${testCSC.dll}" /> 
    <define name="RELEASE" /> 
</csc>

Tip

To determine which additional JAR files an optional task needs, see http://ant.apache.org/docs/manual/index.html#librarydependencies, which lists the needed libraries for each optional taskand where to get them.

Table 1-4. Optional Ant tasks

Task name

Description

antlr

Runs the ANTLR Translator Generator Language Tool.

attrib

Changes the permissions and/or attributes of a file.

cab

Creates CAB files (Microsoft archives).

chgrp

Changes file groups on Unix.

chown

Changes file ownership.

depend

Determines which class files are out-of-date compared to their source.

echoproperties

Lists the project's properties.

ftp

Supports a basic FTP client.

icontract

Generates a property file for iContract, an application for controlling assertions.

image

Performs bulk image manipulation.

jarlib-available

Checks for the presence of an extension.

jarlib-display

Displays the "Optional Package" and "Package Specification" information for JAR files.

jarlib-manifest

Generates a manifest with required dependencies.

jarlib-resolve

Searches for the location of a JAR file, setting the location to an ANT property.

javacc

Invokes the JavaCC compiler.

javah

Generates C header and source files for the Java Native Interface (JNI).

JPCoverage

Runs the JProbe coverage analyzer.

JcovMerge

Merges JProbe coverage snapshots.

JcovReport

Takes a JProbe coverage snapshot and creates a report.

jdepend

Uses the JDepend parser to generate code quality metrics.

jjdoc

Invokes the JJDoc documentation generator (used with JavaCC).

jjtree

Inserts parse tree building actions into source code using the JJTree preprocessor for the JavaCC compiler.

jlink

Deprecated. Merges archive contents. Use the zip and jar tasks with the zipfileset and zipgroupfileset attributes instead.

jprobe

Runs various tools from the JProbe suite.

jspc

Deprecated. Compiles JSP pages to Java source code. Use Tomcat's jspc task instead.

junit

Runs unit tests using JUnit.

junitreport

Merges separate XML files generated by the JUnit task into a single XML file.

maudit

Highlights stylistic and potential execution problems using the Metamata Metrics/WebGain Quality Analyzer.

mimemail

Deprecated. You can still send mail using the mail task.

mmetrics

Generates metrics using the WebGain's Metameta Metrics Quality Analyzer.

mparse

Takes a grammar file, and compiles it with MetaMata's MParse compiler.

native2ascii

Takes a native encoded file and converts it to ASCII.

netrexxc

Compiles all NetRexx source files.

propertyfile

Creates or modifies property files.

pvcs

Gets latest source code from a PVCS repository.

renameextensions

Deprecated. You can achieve the same results by using the move task and using a glob mapper.

replaceregexp

Replaces matched text with new text.

rexec

Controls a rexec session from Ant.

rpm

Builds Linux RPM installation files.

scp

Moves files to and from a remote SSH server.

script

Executes an Apache BSF script.

Scripdef

Defines Ant tasks from scripts.

serverdeploy

Runs a hot-deployment tool for a J2EE server.

setproxy

Configures web proxy properties.

sound

After a build, plays a sound file letting you know whether the build succeeded or failed.

splash

Displays a splash screen.

sshexec

Executes a command on a remote server using SSH.

stylebook

Uses Apache Stylebook to generate book documentation.

symlink

Makes, deletes, or edits Unix symbolic links.

telnet

Controls a Telnet session from ANT.

test

Executes a JUnit test.

translate

Translates keywords in files using values in resource bundles.

vajload

Loads files for Visual Age for Java source control.

vajexport

Exports packages for Visual Age for Java source control.

vajimport

Imports files for Visual age for Java source control.

wljspc

Compiles JSP pages using Weblogic's JSP compiler.

xmlvalidate

Validates XML files and reports any errors.

In addition to these tasks, specific Ant tasks for .NET are shown in Table 1-5.

Table 1-5. .NET Ant tasks

Task name

Description

Csc

Invokes the C# compiler.

vbc

Invokes the VB.NET compiler.

jsharpc

Invokes the J# compiler.

ildasm

Disassembles from .NET intermediate language back to source code.

ilasm

Assembles code into .NET intermediate language.

WsdlToDotNet

Given a WSDL file, this task will generate C# or VB code.

ImportTypelib

COM library importer.

Specific tasks for the Clearcase version control system are listed in Table 1-6.

Table 1-6. Clearcase Ant tasks

Task name

Description

CCCheckin

Checks in files.

CCCheckout

Checks out files.

CCUnCheckout

Un-checks out files.

CCUpdate

Executes cleartool update.

CCMklbType

Executes cleartool mklbtyle.

CCMklabel

Executes cleartool mklabel.

CCRmtype

Executes cleartool rmtype.

CCLock

Executes cleartool lock.

CCUnluck

Executes cleartool unlock.

CCMkbl

Executes cleartool mkbl.

CCMkattr

Executes cleartool mkattr.

CCMkdir

Executes cleartool mkdir.

CCMkelem

Executes cleartool mkelem.

Many EJB specific tasks are shown in Table 1-7.

Table 1-7. EJB-related Ant tasks

Task name

Description

blgenclient

Generates a client JAR for Borland application servers.

ddcreator

Creates EJB deployment descriptors, given a group of WebLogic deployment descriptors.

ejbc

Invokes WebLogic's ejbc tool.

Iplanet-ejbc

Invokes iPlanet's ejbc tool.

ejbjar

Invokes the ejbjar tool (used for many application servers).

wlrun

Starts a WebLogic server.

Wlstop

Stops a WebLogic server.

The Perforce source control tasks are shown in Table 1-8.

Table 1-8. Perforce Ant tasks

Task name

Description

P4Sync

Synchronizes files with the Perforce server.

P4Change

Gets a list of current changes from the Perforce server.

P4Edit

Checks out files for editing.

P4Submit

Checks in files.

P4Have

Lists all client-viewable files.

P4Label

Makes a label based on the files in the current workspace.

P4Labelsync

Syncs with a label.

P4Counter

Gets or sets a counter value. (Counters can be used to keep track of build events, such as the number of builds that have been executed.)

P4Reopen

Reopens a checked-out file.

P4Revert

Reverts file(s) that have been changed to their original content.

P4Add

Adds file(s) to the list to be submitted to the server.

P4Delete

Deletes file(s).

P4Integrate

Integrates file(s). You must specify the source file(s) and the target file(s).

P4resolve

Resolves file(s) in case others have made changes to the file(s) when you were working on it.

P4Fstat

Views differences with the server.

Many tasks for Microsoft Visual Source Safe are detailed in Table 1-9.

Table 1-9. Visual Source Safe tasks

Task name

Description

vssget

Gets a copy of a particular VSS file.

Vsslabel

Makes a new label for the current version of a file.

Vsshistory

Displays a file's history in the project.

Vsscheckin

Checks in files to VSS.

Vsscheckout

Checks out files from VSS.

Vssadd

Adds a new file to VSS.

Vsscp

Changes the project considered the current project by VSS.

Vsscreate

Makes a new project.

Continuing with source control repository tasks, Table 1-10 shows tasks for working with Starteam source control.

Table 1-10. Starteam Ant tasks

Task name

Description

STCheckout

Checks out files from StarTeam projects

STCheckin

Checks in files to StarTeam projects

STLabel

Creates a new label for this project

STList

Displays a list of files in the project

Table 1-11 shows tasks for the Continuous source control server.

Table 1-11. Continuous/Synergy Ant tasks

Task name

Description

CCMCheckin

Checks in files to the source manager

CCMCheckout

Checks out files from the source manager

CCMCheckinTask

Checks in all files in the current task

CCMReconfigure

Reconfigures an existing command

CCMCreateTask

Creates a task

Finally, Table 1-12 lists optional tasks for supporting SourceGear's SourceOffSite Visual Source Safe plug-in.

Table 1-12. SourceOffSite Ant tasks

Task name

Description

Sosget

Gets a read-only copy of a file

Soslabel

Creates a label for the current project

Soscheckin

Checks in files to the source manager

Soscheckout

Checks out files from the source manager

In addition to the built-in and the optional tasks, Ant supports third-party and custom tasks (yes, that's a large number of tasks you can use!). As you'd expect, third-party tasks add functionality to Ant; as an example, take a look at the third-party tasks available for free at http://ant-contrib.sf.net/, which includes a set of tasks for use with Ant and C++. Creating Ant tasks is easier than you might think, and you're going to create your own in Chapter 11.

Dependent Tasks

Typically, you create an Ant build file with a default target named something like main; this target then acts as a master target, handling program flow for the entire build process. It tells Ant to run other targets and specifies their ordering. This is accomplished through the target element's depends attribute.

For example, you might want to add a target named compile to compile your code and add another target called compress to put the compiled code into a JAR file:

<?xml version="1.0" ?>
<project default="main">

    <target name="main">
        <echo>
            Building the .jar file.
        </echo>
    </target>
  
    <target name="compile">
               <javac srcdir="."/>
               </target>
  
               <target name="compress">
               <jar jarfile="Project.jar" basedir="." includes="*.class" />
               </target>

</project>

Ensure that the compile and compress targets runin that orderby assigning the string "compile, compress" to the default target's depends attribute:

<?xml version="1.0" ?>
<project default="main">

    <target name="main" depends="compile, compress">
        <echo>
            Building the .jar file.
        </echo>
    </target>
  
    <target name="compile">
        <javac srcdir="."/>
    </target>
  
    <target name="compress">
        <jar jarfile="Project.jar" basedir="." includes="*.class" />
    </target>

</project>

When you run Ant, it'll look for build.xml and execute the default target, which the project element indicates is main. The main target's depends attribute tells Ant to run the compile target and then run the compress target before running the body of the main target.

Warning

Though you use this attribute to indicate the order targets should run in, targets can still fail, which means you're not guaranteed that they will all behave as expected. Generally, a failed target will stop the Ant build process, but that's not always the case.

Bear in mind that dependencies can be nested inadvertently. For example, take a look at this build file fragment:

<target name="find"/>
<target name="inspect" depends="find"/>
<target name="test" depends="inspect"/>
<target name="purchase" depends="test, inspect, find"/>

If target purchase was the default target, you might think that targets test, inspect, find, and purchase were executed in that order. However, target test depends on target inspect, which depends on find, and so on. An Ant target gets executed once even when multiple targets depend on it. Because the dependencies of a task are executed before the task, the actual order of execution here is find, inspect, test, and then purchase.

Properties

In addition to targets and tasks, the third pillar of an Ant build file is its properties. Properties are name-value pairs that act much like constants in Java code. You set the value of a property with the property element and can refer to that property by name throughout your build file. You can insert the value of a property in task attributes by dereferencing the property name with ${ property-name }.

For example, if you had a property named bin corresponding to the output directory of your build and wanted to refer to that directory, you could refer to it as ${bin} when you assign it to task attributes in your build file. If you wanted to refer to the archives subdirectory in that output directory, you could refer to it as ${bin}/archives. The advantages to this approach should be obvious to anyone who's had to change a directory name in 300 different places throughout an application.

Tip

A forward slash will work as a directory delimiter even on Windows systems; Ant is smart enough to know what you mean.

Property attributes

Properties are used the same way as constants are in Java: they let you collect definitions in one centralized place rather than having them dispersed throughout a build file. When you want to change property values, you can make changes in one location and know that they will propagate throughout the build file. You can see the attributes of the property element in Table 1-13.

Table 1-13. The property element's attributes

Attribute

Description

Required

classpath

The classpath to use when looking for a resource.

No

classpathref

The classpath to use when looking for a resource, which can then be given as a reference to a path element later in the build file.

No

environment

The prefix to use when retrieving environment variables. For example, if you specify environment="env", you will be able to access operating-system-specific environment variables as property names like ${env.PATH}.

A resource, file, url, or environment attribute is required when not using the name attribute.

file

The name of a property file to load values from.

A resource, file, url, or environment attribute is required when not using the name attribute.

location

Sets the property to the absolute filename of the given file. If an absolute path is supplied, it's left unchanged (with / and \ characters converted for the current platforms). Otherwise, the supplied filename is taken as a path relative to the project's base directory and then expanded.

A value, location, or refid element is required when using the name attribute.

name

The name of the property to set.

No

prefix

The prefix to add to properties loaded from a file or a resource. A . is appended to the prefix if none is specified.

No

refid

A reference to a (previously) defined object.

A value, location, or refid element is required when using the name attribute.

resource

The resource name of the property file, used for searching the classpath.

A resource, file, url, or environment attribute is required when not using the name attribute.

url

The URL from which to read properties.

A resource, file, url, or environment attribute is required when not using the name attribute.

value

The value of this property.

A value, location, or refid element is required when using the name attribute.

As an example, you can store a message that displays "Building the .jar file." in a property named message:

<?xml version="1.0" ?>
<project default="main">

    <property name="message" value="Building the .jar file." />
        .
        .
        .
</project>

Tip

You declare properties outside your targets. As of Ant 1.6, all tasks can be declared outside of targets (earlier versions only allowed property, typedef and taskdef to be used outside of a target element). When you define tasks external to a specific target, those tasks are evaluated before any targets are executed.

You can echo the message to the console like this:

<?xml version="1.0" ?>
<project default="main">

    <property name="message" value="Building the .jar file." />
        .
        .
        .
    <target name="main" depends="compile, compress">
        <echo>
                  ${message}
                  </echo>
    </target>
  
</project>

Properties are frequently used to hold pathnames, and the property element's location attribute is useful in this context. Suppose you're storing your source code in a subdirectory of the current directory named source and want to deploy the .jar file created by this build file to a directory named bin. You can create properties corresponding to these directories:

<?xml version="1.0" ?>
<project default="main">

    <property name="message" value="Building the .jar file." />
    <property name="src" location="source" />
                  <property name="output" location="bin" />

    <target name="main" depends="init, compile, compress">
        <echo>
            ${message}
        </echo>
    </target>
        .
        .
        .
</project>

The default target in this build file, main, depends on an init target where the mkdir task (detailed in Chapter 3) is used to create the output directory:

<?xml version="1.0" ?>
<project default="main">

    <property name="message" value="Building the .jar file." />
    <property name="src" location="source" />
    <property name="output" location="bin" />

    <target name="main" depends="init, compile, compress">
        <echo>
            ${message}
        </echo>
    </target>
  
    <target name="init">
        <mkdir dir="${output}" />
    </target>
        .
        .
        .
</project>

Now you can compile the Java source code from the ${src} directory, placing the created .class file in the ${output} directory, and create the Project.jar file in the ${output} directory, all using properties:

<?xml version="1.0" ?>
<project default="main">

    <property name="message" value="Building the .jar file." />
    <property name="src" location="source" />
    <property name="output" location="bin" />

    <target name="main" depends="init, compile, compress">
        <echo>
            ${message}
        </echo>
    </target>
  
    <target name="init">
        <mkdir dir="${output}" />
    </target>
  
   
                      <target name="compile">
                  <javac srcdir="${src}" destdir="${output}" />
                  </target>
  
                  <target name="compress">
                  <jar destfile="${output}/Project.jar" basedir="${output}" 
             includes="*.class" />
                  </target>
</project>

The relative paths used will be expanded in a platform-specific way, something like this in Unix:

-bash-2.05b$ ant -f properties.xml
Buildfile: properties.xml

init:
    [mkdir] Created dir: /home/steve/bin

compile:
    [javac] Compiling 1 source file to /home/steve/bin

compress:
      [jar] Building jar: /home/steve/bin/Project.jar

main:
     [echo] 
     [echo]             Building the .jar file.
     [echo]         

BUILD SUCCESSFUL
Total time: 2 seconds

Here's the Windows version:

C:\ant\ch01>ant -f properties.xml
Buildfile: properties.xml

init:
    [mkdir] Created dir: C:\ant\ch01\bin

compile:
    [javac] Compiling 1 source file to C:\ant\ch01\bin

compress:
      [jar] Building jar: C:\ant\ch01\bin\Project.jar

main:
     [echo]
     [echo]             Building the .jar file.
     [echo]

BUILD SUCCESSFUL
Total time: 4 seconds

Built-in properties

Ant gives you access to the same system properties you'd have access to in Java code, as if they were Ant properties. For example, if you want to determine the name of the operating system, you can refer to ${os.name} in your build file.

Tip

For a list of system properties, see the Java documentation of the System.getProperties( ) method.

Ant has some additional Ant-specific properties:

ant.file

Contains the absolute path of the build file

ant.java.version

Contains the JVM version Ant is using (can hold only 1.1, 1.2, 1.3, 1.4 and [as of Ant 1.6] 1.5)

ant.project.name

Holds the name of the project that is executing (set with the name attribute of project)

ant.version

Contains the version of Ant running

basedir

Holds the absolute path of the project's base directory (set with the basedir attribute of project)

Get Ant: The Definitive Guide, 2nd Edition now with the O’Reilly learning platform.

O’Reilly members experience books, live events, courses curated by job role, and more from O’Reilly and nearly 200 top publishers.