Ant brings pure Java portability, flexibility to key build tool options
Build tool options for Java developers have been limited mostly to older UNIX-based tools, such as Make. Make and its open source derivatives can get the job done, but using them often relies on calling UNIX or Windows commands to do the heavy lifting. That means that even though the Java code is cross-platform and write-once-run-anywhere, the build system generally is tied to one platform.
Java developers looked at this problem and realized that by leveraging the Java platform, they could create a much more powerful build tool, one specifically designed for Java programmers and not bound to any specific platform. The result is Ant, a project managed by the Apache Foundation’s Jakarta project.
Ant configuration files are written as XML documents, so Java programmers should already be familiar with the file syntax, in contrast with the notoriously unfriendly Make syntax. More importantly, all the build system’s actions to build your project, known as tasks, are written in Java; the same build file will run anywhere a Java compiler is available. Everything is self-contained within Ant.
In this article, we’ll look at how to setup and install Ant, create a configuration file to build your project, and use available built-in system and conditional tasks.
Setting up and installing Ant
To get started, we’ll need to head over to the Ant homepage, which contains the most recent release, online manual, and FAQ. Before downloading and installing Ant, you’ll need the Java Development Kit installed (version 1.2 or higher), your JAVA_HOME environment variable set, and the javac compiler in your executable path.
You can download ANT precompiled from the Jakarta site. You'll also want to pick the optional Java Archive (JAR) file, which includes tasks that help integrate with other development tools. Ant is also open source software, so if you want to change any of the internals to help fit your build environment, you could. All you need is to download the source. However, keep in mind that Ant is extremely flexible, and as we'll see in the next article, adding functionality to Ant is easy and doesn't require changing the Ant source code.
Once you’ve downloaded the binary package, you simply need to uncompress the file where you wish to install Ant. For Windows systems, uncompress to c:\ant\; on UNIX systems, you may want to install into /usr/local/ant/ or /opt/ant/.
Next, you’ll need to set your environment variables, specifically ANT_HOME. On Windows, assuming we installed in c:\ant, the commands shown in Figure A will properly set your environment variables.
Set Windows environment variables.
On UNIX, assuming we installed in /usr/local/ant, the commands shown in Figure B will properly set your environment variables.
Set UNIX environment variables.
To install the optional tasks on either Windows or UNIX systems, you need to
copy the optional jar file into the $ANT_HOME/lib/directory. The ant or ant.bat
script will automatically append the jar files into the class path for
you.
Now, let’s test to make sure Ant installed properly. On the command
line, type ant. You should see a message, shown in Figure C,
saying that Ant could not locate a Build.xml file. That’s expected, since we
have to configure and create project files.
Build file error message
Now that Ant is ready to read project files, let’s see what a project file looks
like.
Creating projects
To make life
easier for developers, Ant’s configuration files are written as XML documents.
Developers don’t have to worry about problems with white space (like with
Makefiles), and many developers are already adept at writing valid
XML.
At launch, Ant will automatically try to load the project
configuration file named Build.xml. If you want to name the project
configuration something different, you can run ant with the –buildfile flag,
like so:
ant -buildfile Project_configuration.xml
In the SimpleBuild.xml example configuration file, shown in Listing A, you’ll see a project tag with three attributes: name, default, and basedir. Each tag in Ant configuration files is documented in great detail within the Ant manual. You’ll want to use the Ant manual as a reference to see which are required tags, which are optional, and which have default values.
Within the project tag, you’ll see property and target tags. The property tags create variables that can be accessed by tasks and variable expansion. As we’ll see later, some variables, like the date and time, can be set from within tasks, so not all variables will be explicitly defined.
After the property tags, you’ll see the target tag. You can define multiple targets, each with a different name. You’ll notice that the name of the target tag is compile, which happens to correspond to the default value in the project tag. That means that when we execute Ant, it will automatically start the compile target.
Within the target are a number of tasks, which Ant executes sequentially. You’ll find that almost everything you want to do in the process of building, packaging, and distributing can be handled with the tasks that ship with Ant.
In our simple build, we use the tstamp task to set the current date and time into environment variables. Next, we’ll use the mkdir task to create a directory called ${build}. (Assuming it doesn’t already exist. This is the first example of shell expansion in our script. Ant will automatically expand “${build}” to the value set by the property build, in this case the string build.)
Last, we’ll use the javac task to compile the source code from the directory src and save the output into build.
When we run Ant, we’ll get output showing the status of each target executed, as shown in Figure D.
Ant output
A more in-depth example
Now let’s look at a
slightly more complex configuration that uses multiple targets to
build.
In the example Medium.xml, shown in Listing B, the configuration is broken up into many more
targets than in our SimpleBuild.xml example. Breaking the build process into
different targets means that Ant can enter the build process at any point. In
SimpleBuild.xml, we simply compiled the Java source code. However, in this
example, we initialize the environment (init), compile the code
(compile), package the code into a jar (package), and copy the
result to our production location (dist). We also have a task to clean the
environment by reverting to before any code was compiled.
By
default, we’ll sequentially run init, compile, package, and
then dist. You can see that each target has a defined dependency; Ant
completes dependencies before targets that rely on them. The default target is
dist, so running ant on the command line would do all of the
tasks.
However, we can execute just a portion of the steps by specifying
the desired target on the command line. For example, we can only package the
code, not distribute it. Breaking up larger projects into multiple targets will
help in the debugging and quality assurance process by allowing developers to
quickly make builds of subsections, rather than wait for a complete
build.
Built-in tasks
Now that you’ve seen
how to create a project file, let’s look at some of the built-in tasks. You’ll
want to look at the documentation for Ant
to get specifics on the tasks, since there’s a lot more info than we can cover
here.
File System Tasks
You’ll probably
use Ant most frequently for system tasks: moving, modifying, copying, and
deleting files. You’ll need to move files around when you do distribution and
when you clean up temporary files. That’s why having a good understanding of the
file system tools is essential.
Our example Fs.xml, shown in Listing C, echoes a message to the filesystem. The “@…@”
designation is how Ant does text substitution. You must designate tokens to be
replaced by putting the “@” symbols around the text to be replaced. After the
message is copied onto the disk, we create two directories, copy the files
around, do a token substitution of the file on disk when we copy it, and delete
one of the copied files. Figure E shows the output of running Ant on the
Fs.xml build file.
Output of the filesystem example
Using conditionals
Building conditionals in Ant
isn’t easy. Because of the way Ant builds tasks and targets, you’ll have to
carefully construct your statements. Conditionals work by executing targets only
if a property is set to true. You can use and, or, and not
statements to construct your conditionals. When a conditional is found to be
true, you can use the antcall task to execute another target. Let’s look
at a simple example that determines if the optional sound task is available and
if it is available on UNIX or Windows.
In the SoundConditional example,
shown in Listing D, you’ll see that the condition task will call
the two conditional statements, condWinSound and condUnixSound, but neither will
execute unless the conditional properties are set. The conditional targets check
to see if the package is available (it's part of the optional jar file) and on
which platform it is available.
Wrapping it up
By now, you should be ready to start
moving your own software projects into the Ant build tool. Ant is being used
more and more by developers to support large Java projects—and for good reason.
The tools are Java-oriented, cross-platform, and generally easier to use than
UNIX-oriented tools. Hopefully, this article gave you a look into the power of
Ant and can help increase productivity in your organization. In future
installments, we’ll look at how you can extend Ant by creating your own tasks.