Tutorials

ANT Tutorial 101

Introduction

ANT is the acronym for Another Neat Tool. It's a simple (yet, very sophisticated) utility that can be used to compile, run, and deploy Java applications without having to worry about IDE-specific quirks. The tool itself is built in Java and has an XML-based configuration file.

The learning curve for ANT is fairly small and once setup, you typically will not have to change it too much (although I've ended up making changes quite a few times myself). This tutorial provides a simple introduction to ANT and will also provide some example scripts that will help you get started with simple projects. I hope to add the most commonly used tasks in ANT in future.

 

A little bit of history

Before ANT came into exsitence, the most commonly used tool was Make, a (mainly) UNIX based tool that was used to build and deploy applications. Although Make was intended for C and C++ applications, it was possible to use it for Java applications. However, Make was pretty finicky when it came to handling space characters, tab characters, newlines, etc. Also, it was not really portable across different platforms.

Given these constraints, and with the increasing popularity of XML files for defining data, ANT was born.

Installation and Configuration

Getting the software is pretty easy. Just download the latest version (1.6.5 as of this writing) from http://ant.apache.org. The installation comes with the JAR files and some batch scripts that can be used to run the program.

If you are using Eclipse as your IDE, then ANT is already there (although Eclipse does not use it directly). I'll discuss the details on how to run ANT shortly.

Prerequisites

This tutorial contains incremental examples. It is best that you have a small Java project that you can ANTify before you go through the remainder of the tutorial so that you can have hands-on experience. I will assume that your code is structured in the following (conventional) manner.

+- Project
   +- src
      <Source files>
   +- classes
      <Compiled class files>
   +- lib
      <3rd party library files>
   +- build
      <Directory where our project will be deployed to. Empty for now>
   +- docs
      <Directory where API documentation will be placed Empty for now>
   +- build.xml  // The ANT build file that we will use - can be empty initially

That done, let's get on with writing our first ANT file.

Core concepts

ANT essentially is a Java application that can build and deploy a Java application based on configuration details specfied by the application developer written in the form of an XML file. The convention is to name this file as build.xml and place it at the root of the application's installation folder. You can technically name this anyhow you want to, but unless you have very specific reasons for doing so, it is best to follow standard industry practices.

Let's now look at the barebones version of ANT file (type the contents into the empty build.xml file created earlier).

<?xml version="1.0" encoding="ISO-8859-1"?>
<project name="AntExample" basedir=".">
</project>

This is as basic as it gets. Here, we have defined a project with the name AntExample and have specified that the base directory (for relative paths later on) as the root directory of the project (directory where the build.xml file is located).

This by itself does not do much. In order for ANT to do anything, we have to define targets that ANT can perform.

Cleaning existing files

A good first target would be to clean the existing compiled and built files if any. So, let's add that.

<?xml version="1.0" encoding="ISO-8859-1"?>
<project name="AntExample" basedir="." >
    <target name="clean" description="Delete all generated files">
        <delete dir="${basedir}/classes"/>
    	<delete dir="${basedir}/build"/>
    </target>
</project>

Here, we are asking ANT to delete the directory classes and build under the base directory. While this is perfectly fine, we might not want to hard code even relative classpaths inside the targets. Instead, we would want to define some standard paths as constants and refer to them inside the targets so that if the paths change, we have to change it in only one place (much like defining constants for numbers inside a program). Here is a modified version.

<?xml version="1.0" encoding="ISO-8859-1"?>
<project name="AntExample" basedir="." >
	<property name="build.dir" value="${basedir}/build"/>
	<property name="classes.dir" value="${basedir}/classes"/>

    <target name="clean" description="Delete all generated files">
        <delete dir="${classes.dir}"/>
    	<delete dir="${build.dir}"/>
    </target>
</project>

As you might have noticed, you can refer to properties and some default ANT attributes using the ${..} notation. We have deleted whatever we had. It's only fair now to compile our program afresh now. Let's see how to do that.

Compiling a Java project

Since this is an incremental example, I am going to show only the new lines being added. The good part about ANT is that it's segmented. The whole file can be broken down into various targets and some general properties defined at the beginning. So, the code samples will not overlap each other.

<target name="compile" description="Compile the application" depends="clean">
    <mkdir dir="${classes.dir}"/>
    <javac destdir="${classes.dir}">
        <classpath>
        	<fileset dir="${lib.dir}">
        		<include name="**/*.jar"/>
        	</fileset>
        </classpath>
        <src path="${src.dir}"/>
    </javac>
</target>

That's quite a bit. Before I start explaining, you might see that I've added two new properties that haven't been defined - lib.dir and src.dir. So, let's go add them to the top of the file.

<property name="src.dir" value="${basedir}/src" />
<property name="lib.dir" value="${basedir}/lib" />

The first interesting aspect of this target is that there is a depends attribute on the target, saying that this target is dependent on another target called clean. In ANT, you can chain targets together so that they are performed one after the other. In this case, if you call the target compile, it's going to see that the target is dependent on another target called clean and is going to execute that target first before coming back and executing this one.

Since we have deleted the classes directory in the clean target, we are first creating it here.

<mkdir dir="${classes.dir}"/>

The next main step is to compile our Java source files in the src directory and place them in the classes directory. As a part of the compilation, we might also want to put all the JAR files in the lib directory in the classpath so that the compilation works properly.

The javac task is a core ANT task that comes with the package. The task invokes the standard javac command that comes packaged with the JDK and compiles the project.

Setting up the JAVA_HOME environment variable
In order for javac task to work properly, you should set the JAVA_HOMEenvironment variable to point to your JDK root directory (JDK and not JRE).

To set the environment variable,

  1. Right-clik the My Computer icon on the desktop
  2. Select Properties from the menu options
  3. Select the Advanced tab
  4. Click on the Environment Variables button
  5. Click on either of the Edit... buttons
  6. Enter JAVA_HOME as the key and the path to your JDK installation (ex. c:\j2sdk1.5.0_03) as the value
  7. Click OK.

At the minimum you need to specify two things in the javac task - the root directory under which all your source files that need to be compiled are present

<src path="${src.dir}"/>

and the directory where the compiled class files should be placed.

destdir="${classes.dir}

The first one is a child tag inside the javac tag, whereas the second one is an attribute of the javac tag.

Almost always, you would need to specify the classpath for the compilation that points to the third-party libraries that need to be included as a part of the compilation. This can be done using the classpath child element.

<classpath>
    <fileset dir="${lib.dir}">
        <include name="**/*.jar"/>
    </fileset>
</classpath>

There are a number of other parameters that you can specify either as an attribute or as a child element to javac, such as optimization level, JDK version compatibility, etc. For more information, refer to the Apache ANT Manual.

At this point, I think you'll be itching to see if this thing really works. So, let's skip ahead to see how we can get this going.

Running ANT

In order to run ANT, you need to do two things first.

  1. Setup the ANT_HOME environment variable (much like how it was done for the JAVA_HOME variable) to point to the ANT installation folder (ex. C:
    apache-ant-1.6.5)
  2. Edit the PATH system environment variable and include the path to the bin directory under the ANT installation folder (ex. c:
    apache-ant-1.6.5
    bin) so that the ant command can be called from anywhere.

That done, do this to execute your ant target.

  1. Open a Command Prompt window.
  2. Go to the root directory of your project (ex. C:\Projects\ProjectName)
  3. Type ant compile

Successful run

This command essentially invokes the ant script present under the {{$ANT_HOME
bin}} directory and calls the compile target. Since no specific build file was specified, it defaults to build.xml. If you've setup everything right, you should see the following messages.

D:\Projects\Personal\AntTest>ant compile
Buildfile: build.xml

clean:
   [delete] Deleting directory D:\Projects\Personal\AntTest\classes
   [delete] Deleting directory D:\Projects\Personal\AntTest\build

compile:
    [mkdir] Created dir: D:\Projects\Personal\AntTest\classes
    [javac] Compiling 1 source file to D:\Projects\Personal\AntTest\classes

BUILD SUCCESSFUL
Total time: 4 seconds

ant script could not be found

If you see something like this

'ant' is not recognized as an internal or external command, operable program or batch file.

it means that you have not updated your PATH variable properly. It could be because of the following reasons.

  • The path you added at the end of the file does not to the ANT installation's bin direcotry (ex. c:\apache-ant-1.6.5\bin and not C:\apache-ant-1.6.5.)
  • You did put a semi-colon ( between the existing path and the one that you typed (the PATH variable can have multiple directories, separated by semi-colons).
  • Your path contains spaces (ex. C:\Program Files\apache-ant-1.6.5). In this case, simply wrap your directory path within double-quotes, like "c:\Program Files\apache-ant-1.6.5\bin.

build.xml file not present

If you see something like this

Buildfile: build.xml does not exist!
Build failed

it means that you are not in the right directory. Make sure you are in the root directory of your project and that the build.xml file is under that directory.

Invalid target

If you see something like this

Buildfile: build.xml

BUILD FAILED
Target 'compile' does not exist in this project.

Total time: 0 seconds

it means that you did not type things properly inside the build.xml file. Go back and verify.

If none of these happened, CONGRATULATIONS!. You just ran your first ANT target! It's as simple as that. Whew! Now that you've gotten a taste of how simple and ANT can be, you might be interested in knowing how cool ANT can be. ANT may look like a simple script, but we've just scratched the surface. There are a lot more targets that you can specify using ANT, and like most Java tools, you can even extend it to create your own custom targets.

So, let's move forward and take care of other common things that are normally done with ANT.

Running the application

Now that we know how to use the ANT script, let's see how we can use it to run our precious application.

<target name="run" description="Run the application" depends="compile">
	<java classname="com.cssathya.examples.ant.HelloWorld">
       	<classpath>
       		<pathelement path="${classes.dir}"/>
       		<fileset dir="${lib.dir}">
       			<include name="**/*.jar"/>
       		</fileset>
       	</classpath>
	</java>
</target>

The target, of course, depends on the compile target, because you have to compile your program first before you can run anything. The java task can be used to invoke the java application. In order for this to work properly, make sure you have set your JAVA_HOME variable properly. The classpath element can be used to define the classpath for the application. The element, in turn, contains pathelement to define directories where class files are present and fileset tags where third-party JAR files can be located. Most importantly, the classname attribute in the java task defines the main class that needs to be invoked.

As before, open a command prompt and go to the root directory of your project and type ant run. You should see an output similar to the following (may vary depending on what your program does.

D:\Projects\Personal\AntTest>ant run
Buildfile: build.xml

clean:
   [delete] Deleting directory D:\Projects\Personal\AntTest\classes

compile:
    [mkdir] Created dir: D:\Projects\Personal\AntTest\classes
    [javac] Compiling 1 source file to D:\Projects\Personal\AntTest\classes

run:
     [java] Hello World!

BUILD SUCCESSFUL
Total time: 2 seconds

It's as simple as that!

Creating a build

You've compiled all your classes and even run your application. That's great, but you don't normally send class files to people. You need to package it neatly. Let's now see how you can create a build with ANT.

<target name="deploy" description="Deploy the application" depends="compile">
    <!-- Create a directory where the build files will be placed -->
    <mkdir dir="${build.dir}" />
    <mkdir dir="${build.dir}/lib" />

    <!-- Make a JAR file -->
    <jar destfile="${build.dir}/lib/${ant.project.name}.jar">
    	<fileset dir="${classes.dir}"/>
    </jar>

    <!-- Copy libraries used exclusively by this project -->
    <copy todir="${build.dir}/lib">
    	<fileset dir="${lib.dir}">
    		<include name="**/*.jar"/>
    	</fileset>
    </copy>
</target>

Since we cannot make a build without compiling our source files, this target is made dependent on the compile target. Then, the build directory is recreated (it was deleted in the clean target).

The way to package Java class files is using a Java Application aRchive or JAR file. The jar tag helps us do just that. The fileset child tag can be used to specify the root folder where the class files can be found.

If the application depends on other third-party libraries, they need to be copied as well. A simple copy tag will do the trick.

Creating documentation

You've compiled, ran, and deployed your application. It's always a good idea to provide some documentation to your code when you are creating a build. It's not nice otherwise. One of the first forms of documentation that you can create without spending too much time is the API documentation. The following snippet shows how you can do this with ANT.

<target name="docs" description="Generate Javadocs">
	<delete dir="${docs.dir}"/>
	<mkdir dir="${docs.dir}"/>
	<mkdir dir="${docs.dir}/api"/>
	<javadoc destdir="${docs.dir}/api" author="true" version="true" use="true" windowtitle="ANT Test API">
		<packageset dir="${src.dir}" defaultexcludes="yes" />

		<doctitle><![CDATA[<h1>ANT Test Application</h1>]]></doctitle>
		<bottom>
		    <![CDATA[<i>Copyright &#169; 2005 All Rights Reserved.</i>]]>
		</bottom>
	</javadoc>
</target>

As you can see, this target needs one extra property

<property name="docs.dir" value="${basedir}/docs"/>

Let's have a closer look at the target itself. Since the documentation is generated from the source files, this target does not have to depend on any other target.

The target essentially deletes the existing documentation, and creates the directory afresh. The packageset tag defines the folder where Java source files can be found, the doctitle tag defines the header for the pages, and the bottom tag defines the footer for the pages.

As before, open a command prompt and go to the root directory of your project. Then type ant docs in the command prompt to run the target. You should see output similar to what's shown below.

D:\Projects\Personal\AntTest>ant docs
Buildfile: build.xml

docs:
   [delete] Deleting directory D:\Projects\Personal\AntTest\docs
    [mkdir] Created dir: D:\Projects\Personal\AntTest\docs
    [mkdir] Created dir: D:\Projects\Personal\AntTest\docs\api
  [javadoc] Generating Javadoc
  [javadoc] Javadoc execution
  [javadoc] Loading source files for package com.cssathya.examples.ant...
  [javadoc] Constructing Javadoc information...
  [javadoc] Standard Doclet version 1.5.0_06
  [javadoc] Building tree for all the packages and classes...
  [javadoc] Building index for all the packages and classes...
  [javadoc] Building index for all classes...

BUILD SUCCESSFUL
Total time: 2 seconds

This concludes our first part of the tutorial. I will cover the more advanced concepts in [ANT Tutorial 201] shortly.

References