Build tools have great importance in transforming source code and other input files into an executable form. For complex applications, it is very important to ensure that precisely the same build steps are carried out during each build and in order to produce consistent builds in a timely manner. Automating the whole process is also something that software developers need. Build tools provide all this.

C/C++ uses a build took called make. There are tasks and the dependencies are defined amoung the tasks. The build tasks are performed by invoking shell commands.

Apache Ant (acronym for another neat tool) is a Java-based build tool. Ant is similar to make as it also has tasks and we define dependencies between tasks. The difference is that instead of implementing build tasks using platform-specific shell commands, ANT uses cross-platform Java classes.


Platform independence

ANT provides platform independence, which means that you can write a single build file and it will operate consistently on any Java platform. This is ANTís greatest strength.


Build file

ANT build files are written in XML. We use XML elements that Ant understands, and new elements can be defined to extend Ant's capabilities. A build file consists of a single top-level project element. This project element contains one or more target elements. A target performs any number of operations, such as compiling a set of source files, deleting files etc. You are not supposed to write script for these operations because these operations are performed by specialized task tags.

All the operations you require for the build process can be placed under one target element. But this will reduce flexibility. Normally you split the operations into logical steps and each logical step is placed under a target element. In this way, you may execute only the targets which are required.

A simple build file is given below. Default attribute is used with the project to indicate the default target.

Java Code:
<?xml version="1.0"?>
<project default="init">
<target name="init">
</target>
</project>
Adding description

Project elements can contain name and description attribute apart from default attribute. The target element can also have description and name attribute. The description is used to add some useful details which provide clarity.

Java Code:
<?xml version="1.0"?>
<project default="init" name="XML parsing">
<description>
A simple project for XML parsing.
</description>
<!-- XML comments can also be used -->
<target name="init" description="Initialize parsing engine.">
<!-- perform initialization steps here -->
</target>
</project>

Properties

Properties have a name and a value. You may say that it is like variables in a programming language. Thing to note is that Ant properties cannot be changed once they are set. What if you try to give an existing property a new value?? No error is shown and the property does retain its old value. The mechanism for setting properties in Ant looks like this:

Java Code:
<property name="sports" value="football"/>
To use or to refer to this property, use the following syntax:

Java Code:
${sports}
You are free to use a property in some other property. For example:

Java Code:
<property name="sports-database" value="${sports}.db"/>

Ant provides predefined properties which you may use as required. All the system properties are available. For example: ${user.home}. Apart from this, Ant defines a small set of its own properties, like

${ant.version} (version of Ant)
${basedir} (absolute path of the project's directory)


You also have some properties to refer to files and directories on the filesystem. Since Ant provides plateform independence, it also takes care of the problems across different platforms with different path separator characters ( / versus \, for example). Ant provides a location attribute to mention the path in platform-neutral way. For example:

Java Code:
<!-- setting a property -->
<property name="database-file"
location="archive/databases/${sports}.db"/>
<!-- property named: database-file -->
It is up to user to use either back slash or forward slash. The slashes are converted to correct ones for the current platform.

A good tip is to use relative path names instead of absolute ones where possible.


Dependencies

Building process involves compiling source code and packing into JAR files. The involved steps must have a clearly defined order. Question is: how to specify the order of targets in ANT files? Ant uses a flexible approach to deal with this. It defines dependencies among targets. Each ANT target is defined in terms of all the other targets that need to be completed before it can be performed. This is done using the depends attribute of the target element. Example:

Java Code:
<target name="init"/>
<target name="preprocess" depends="init"/>
<target name="compile" depends="init,preprocess"/>
<target name="package" depends="compile"/>
Target named init is independent one, so if you run it, only init will be executed. If you run compile, then init and preprocess will be executed (first init and then preprocess). Please note that a target is executed only once.


Invoking ANT

There are many ways for invoking ANT. ANT files can be written using a text editor (Textpad, notepad, wordpad, UltraEdit etc) or you may use some XML editor as well. Ant comes in command-line form and is invoked from a UNIX or Linux shell prompt or a Windows command prompt.

As a developer, you would prefer ANTís support in your IDE to make things simple. Fortunately, ANT script can be invoked from popular JAVA IDEs like Eclipse.

Let me first show you how to invoke ANT script from command line. If you type ant command on the console, the default build.xml will be executed and the default target will be built. Itís also possible to specify a number of command-line options, followed by any number of build targets. Ant will build each of the targets in order. Donít worry about the dependencies, ANT will resolved dependencies along the way.

Ant looks for a file with the name build.xml which means that if your build file has the same name, then you do not need to specify the build file name. Normally itís a good practice to use the default name. Sometimes it is convenient to have build files with other names, in which case you need to use the-buildfile <file> arguments to Ant ( -f <file> is the abbreviated version).

To set the properties that can then be used in the build file ,-D argument is used. This can be used to override initial property settings in the build file. For example, to set the name property to a particular value, following can be used:

Java Code:
-Dsubject=mathematics
It is important to know that the -D flag sets a property before any information in the build file is read. So if in init target you are assigning some value to the subject property, then ĖD argument wonít have any affect.

Many Java IDEs support Ant. Some of them come with build in support, other needs plugins to support Ant. JEdit, Borland JBuilder, IntelliJ IDEA, the Java Development Environment for Emacs (JDEE), NetBeans IDE, Eclipse, and
WebSphere (R) Studio Application Developer supports Ant.


Ant support in Eclipse

Eclipse provides support for Ant which makes build process really simple. The Eclipse's Ant editor is very useful since it highlights the syntax and provides content assistance.

ANT (Another Neat Tool)-codehighlighter.jpg

After typing a tag, press Ctrl-Space to view a completion list containing the <property> tag, and a short explanation of that task.

Eclipse also provides an outline view that shows the structure of the build file. It actually provides a quick way of navigating through the file.

ANT (Another Neat Tool)-outline.jpg

If your build file has the default name (build.xml), then it will have Ant icon in Eclipse. Right click it, Run As > Ant Build is used to execute the build script.


Building a project

Letís build an environment for a basic Java project. You will need to know Ant tasks for compiling source code and assembling JAR files.

Ant has built-in support for invoking the javac compiler and other Java-related tasks. To write a task that compiles some Java code, use the following:

Java Code:
<javac srcdir="src"/>
This tag looks for all files with extension .java in the src directory and invokes the javac compiler on them. Java class files will be generated in the same directory. It is always a good idea to put the classfiles under a separate directory structure. For that, you need to ass a destdir attribute. You may also add other attributes like: classpath (same as -classpath option on javac), debug="true" (Indicates to the compiler that the source files should be
compiled with debug information)

A good thing about javac task is that it will only compiles those source
files that are really needed to be compiled. Here is how it works: if a classfile already exists, and that classfile's corresponding source file has not been changed since the classfile was generated, then there is no need to re-compile the file. The output of javac task is very useful and it shows the number of source files that were actually compiled.

Ant also defines a target to remove any generated classfiles from that target directory. Its called clear target and you should use it if you want to make sure that all of the source files are compiled (fresh copy).

It might be interesting for you to know that the javac task actually invokes the compiler classes in the same Java virtual machine (JVM) in which Ant itself is running in. So for Ant, only a single JVM instance is required, both to run Ant itself and to perform all of the required compilation tasks. This is a surely more efficient use of resources and leads to greatly improved build times.

There may be times when you want the compiler to be invoked separately. For example: sometime you may wish to specify certain memory options to the compiler. For this, simply set javac 's fork attribute to true:

Java Code:
<javac srcdir="src" fork="true"/>

Creating JARs

Now lets come to creating JAR file/s. You used javac task to compile the source code, now you would like the resulting classfiles packaged into a JAR file. Every JAR file contains a manifest file that can specify properties of the JAR file. Ant provides a jar task for this:

Java Code:
<jar destfile="packagea.jar" basedir="classes"/>
This creates a new JAR file called projecta.jar and adds all the files in the
classes directory to it. You must be knowing that JAR files can contain other resources. In the example above, we did not specify any manifest file, so Ant will provide a basic one.

You can use manifest attribute to specify a file to use as the manifest for the JAR file. The contents of a manifest file are specified within the build file using the manifest task.

Java Code:
<jar destfile="package.jar" basedir="classes">
<manifest>
<attribute name="Built-By" value="${user.name}"/>
<attribute name="Main-class" value="package.Main"/>
</manifest>
</jar>
Sometimes you would want to add time stamp with the output so you may know when it was done. Ant provides a simple but very useful tstamp task for this. This task is usually called at the start of a build (in an init target). It does not need any attributes normally and only <tstamp/> is sufficient is many cases. The tstamp task produces no output. It actually sets three Ant propertiesbased on the current system time and date.

DSTAMP ( set to the current date - default format is yyyymmdd)

TSTAMP (set to the current time - default format is hhmm)

TODAY (string describing the current date, with the month written in full)

Let suppose you have tstamp task, now you can use the Ant properties associated with it where every you need. For example:

Java Code:
<jar destfile="package-${DSTAMP}.jar" basedir="classes"/>
Now the generated jar will have current date with it.

You may also configure tstamp task to use different properties:

Java Code:
<tstamp>
<format property="OFFSET_TIME"
pattern="HH:mm:ss"
offset="10" unit="minute"/>
</tstamp>
Example

Now you know some basics, let me present an example that will make more sense now:

Java Code:
<?xml version="1.0"?>
<project default="dist" name="Project X">
<description>Test project</description>
<property name="srcDir" location="src"/>
<property name="buildDir" location="build"/>
<property name="distDir" location="dist"/>
<target name="init">
<tstamp/>
<mkdir dir="${buildDir}"/>
<mkdir dir="${distDir}"/>
</target>
<target name="compile" depends="init">
<javac srcdir="${srcDir}" destdir="${buildDir}"/>
</target>
<target name="dist" depends="compile">
<jar destfile="${distDir}/package-${DSTAMP}.jar" basedir="${buildDir}">
<manifest>
<attribute name="Built-By" value="${user.name}"/>
<attribute name="Main-Class" value="package.Main"/>
</manifest>
</jar>
<jar destfile="${distDir}/package-src-${DSTAMP}.jar" basedir="${srcDir}"/>
</target>
<target name="clean">
<delete dir="${buildDir}"/>
<delete dir="${distDir}"/>
</target>
</project>
Output:

Java Code:
Buildfile: build.xml
init:
[mkdir] Created dir: C:\tutorial\javaexample\build
[mkdir] Created dir: C:\tutorial\javaexample\dist
compile:
[javac] Compiling 5 source files to C:\tutorial\javaexample\build
dist:
[jar] Building jar: C:\tutorial\javaexample\dist\package-20080417.jar
[jar] Building jar: C:\tutorial\javaexample\dist\package-src-20080417.jar
BUILD SUCCESSFUL
Total time: 5 seconds
The JAR file is named according to the current date. A manifest entry is set for the main class of the application and now you may launch the application from command line using the command

Java Code:
java -jar package-20080417.jar
We also generated a JAR file with source code (package-src-20080417.jar)

Hope this helps.