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.
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.
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>
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 |
---|---|---|
Defines the target name | Yes | |
Comma-separated list of targets to execute before this target | No | |
Name of a property needed to run this task | No | |
Name of a property that can not be set before running this task | No | |
Description of this target's purpose | No |
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.
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 |
---|---|
Executes Ant | |
Executes a target from the current build file | |
From a given build file, creates a DTD reflecting all of the tasks Ant currently knows about | |
Invokes a native executable | |
Sets a Boolean value in a property according to the availability of desired resource | |
Sets a property to the last element of a specified path in an effort to determine a file's name without directory structure | |
Manages build numbers | |
Expands GZip or BZip2 archives | |
Packs GZip or BZip2 archives | |
Creates checksums for one or more files | |
Modifies file permissions on Unix | |
Concatenates multiple files | |
Checks the result of a condition and sets the result to in a property | |
Copies files | |
Interacts with a CVS repository | |
Converts a series of CVS change logs into an XML report | |
Adds entries to a .cvspass file | |
Creates an XML report highlighting the differences between tags | |
Finds the CVS software version | |
Modifies the list of default exclude patterns, affecting which files are automatically excluded from processing by file-related tasks | |
Delete files and folders | |
Deletes target files that are older than new source files | |
Assigns a file's directory path to a property | |
Extends the | |
Echoes text to | |
Invokes a native executable | |
Halts and exits a build by throwing a | |
Sets a token filter that can be used by
filter-related tasks such as | |
Adds or remove tabs, carriage returns, linefeeds, and EOF characters from a set of files | |
Adds a new key to a given keystore | |
Retrieves files using FTP, HTTP, and more from a URL | |
Unpacks a GZip file | |
Packs a GZip file | |
Allows the use of other Ant files | |
Displays a message and reads a line of input from the console, allowing for user input during the build process | |
Creates a JAR archive similar to Java's
| |
Executes the Java interpreter to run a class or application | |
Compiles the specified source file(s) | |
Invokes the | |
Sets a property file to the entire contents of a text file | |
Loans an entire property file into Ant properties | |
Defines a new task as a macro built-up upon other tasks | |
Sends SMTP mail messages | |
Creates an archive's manifest file | |
Makes a new directory | |
Moves a file to another directory | |
Contains other Ant tasks that can be run simultaneously by multiple Java threads | |
Uses the | |
Converts paths between platforms | |
Defines a new task based on an existing task with certain options preset as defaults | |
Sets one or more properties to new values | |
Runs a listener that records the logging output of the build process to a file | |
Replaces a string with another in all files in a directory | |
Invokes the | |
A container task that can contain other Ant tasks and run them in sequence | |
Uses the JarSigner to securely sign ZIP and JAR archives | |
Suspends execution for a specified period of time | |
Runs SQL statements against a database | |
Runs Ant within all subdirectories of the project directory | |
Synchronizes two directory trees | |
Makes a new TAR archive | |
Creates a new task definition and adds it to the current project | |
Sets a temporary filename to an Ant property | |
Sets time-based properties to the current time | |
Creates a new task or data type for use in the current project | |
Unpacks a TAR file | |
Unpacks a WAR file | |
Unpacks a ZIP file | |
Sets a property value to true if a given target file is newer than a set of source files | |
Halts a build and continues when specified conditions are met | |
Creates WAR archive files (an extension of the
| |
Locates a class or resource, either on the current class path or the system class path | |
Loads Ant properties from an XML property file | |
Transforms a set of documents via XSLT | |
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
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 |
---|---|
Invokes the C# compiler. | |
Invokes the VB.NET compiler. | |
Invokes the J# compiler. | |
Disassembles from .NET intermediate language back to source code. | |
Assembles code into .NET intermediate language. | |
Given a WSDL file, this task will generate C# or VB code. | |
COM library importer. |
Specific tasks for the Clearcase version control system are listed in Table 1-6.
Table 1-6. Clearcase Ant tasks
Many EJB specific tasks are shown in Table 1-7.
Table 1-7. EJB-related Ant tasks
The Perforce source control tasks are shown in Table 1-8.
Table 1-8. Perforce Ant tasks
Task name | Description |
---|---|
Synchronizes files with the Perforce server. | |
Gets a list of current changes from the Perforce server. | |
Checks out files for editing. | |
Checks in files. | |
Lists all client-viewable files. | |
Makes a label based on the files in the current workspace. | |
Syncs with a label. | |
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.) | |
Reopens a checked-out file. | |
Reverts file(s) that have been changed to their original content. | |
Adds file(s) to the list to be submitted to the server. | |
Deletes file(s). | |
Integrates file(s). You must specify the source file(s) and the target file(s). | |
Resolves file(s) in case others have made changes to the file(s) when you were working on it. | |
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 |
---|---|
Gets a copy of a particular VSS file. | |
Makes a new label for the current version of a file. | |
Displays a file's history in the project. | |
Checks in files to VSS. | |
Checks out files from VSS. | |
Adds a new file to VSS. | |
Changes the project considered the current project by VSS. | |
Makes a new project. |
Continuing with source control repository tasks, Table 1-10 shows tasks for working with Starteam source control.
Table 1-11 shows tasks for the Continuous source control server.
Finally, Table 1-12 lists optional tasks for supporting SourceGear's SourceOffSite Visual Source Safe plug-in.
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.
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
.
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.
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 |
---|---|---|
The classpath to use when looking for a resource. | No | |
The classpath to use when looking for a
resource, which can then be given as a
reference to a | No | |
The prefix to use when retrieving environment
variables. For example, if you specify | A | |
The name of a property file to load values from. | A | |
Sets the property to the absolute filename of
the given file. If an absolute path is supplied, it's left
unchanged (with | A | |
The name of the property to set. | No | |
The prefix to add to properties loaded from a file or a resource. A . is appended to the prefix if none is specified. | No | |
A reference to a (previously) defined object. | A | |
The resource name of the property file, used for searching the classpath. | A | |
The URL from which to read properties. | A | |
The value of this property. | A |
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
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
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 ofproject
)ant.version
Contains the version of Ant running
basedir
Holds the absolute path of the project's base directory (set with the
basedir
attribute ofproject
)
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.