Introduction to Apache Ant
Filed under: tools java build scripting
There are 0 comments on this article.
Introduction to Apache Ant
Apache Ant is currently the most common Java build scripting tool. Created by James Duncan Davidson while working on an open source project (which later became Apache Tomcat), Ant was developed as a platform neutral build scripting tool for Java projects. Apache Ant was officially released as a standalone product in 2000 and is now the most widely used Java build scripting tool. Lately, Apache Maven has been developed as an alternative build scripting tool for Java. Maven introduces significant capability above and beyond Ant, including an embedded project lifecycle to limit the amount of potential scripting that is required. However, Ant is still the most widely used tool, especially in commerical environments and is supported, enhanced and delivered by vendors such as IBM, BEA and Sun.
In its simplest form, Ant can be used to create and coordinate a sequence of individual build commands. One of the main benefits of Ant, is that like Java itself, Ant is platform neutral and therefore an Ant build script can be executed on any supported Java platform. Ant implements a simple form of build avoidance, in that it looks at the date/time stamps of individual files, to work out what (if any) of the files from your complete application it needs to re-build.
Key Concepts
project - the application, component or library that is to be built.
target - a part of the composite build process, e.g. compile source, create distribution archive.
task - the set of individual commands or operations that are executed to build a target, e.g. create a directory, call the java compiler.
dependency - a hierarchical relationship between targets, if a target has a dependency its dependent target(s) will be executed first.
The input to Ant is a textual build script by default called build.xml (although any filename can be used). A complete application can be built using one or many build scripts (which are commonly located at different component/directory levels). Each build script describes a set of targets, which are the core parts of the composite build process, e.g. compile source code, test, create a Java archive and so on.
Each of the targets can make reference to any of Ant's built-in tasks. A task is basically an interface to a Java object written to carry out a predefined operation, e.g. compile a set of source files, delete a directory structure and so on. Parameters can be specified for the task, defining its exact invocation. There are a large number of built-in tasks (see the Ant manual for details), however since the tasks are interfaces to Java objects, you can quite easily extend Ant by creating new tasks yourselves.
An example of calling Ant from the command line to execute a "release" target would be as follows:
Here the "-f" option is used to specify the name of the build script that you wish to use (atm.xml) and the target which will be executed is the "release" target.
One of the most important things to note is that Ant in itselfis not a compiler, rather it invokes your Java compiler "javac" through its built-in <javac> task. This task, recursively scans source and destination directories to look for Java classes that need to be (re)built and optimizes calls to the Java compiler.
An Example
An example of an Ant build script to compile a set of Java classes (for an ATM application) and produce a releasable ".jar" file is given below:
<?xml version="1.0">
<project name="atm" default="compile" basedir=".">
<property name="dir.src" value="src"/>
<property name="dir.build" value="build"/>
<property name="dir.dist" value="dist"/>
<property name="dir.libs" value="C:\JavaTools\libs"/>
<!-- define a classpath to be used throughout the project -->
<path id="classpath">
<pathelement location="{$dir.build}/>
<!-- include third party libraries -->
<fileset dir="${dir.libs}">
<include name="*.jar"/>
</fileset>
</path>
<!-- initialise directory structure -->
<target name="init" description="initialise directory structure">
<mkdir dir="${dir.build}"/>
<mkdir dir="${dir.dist}"/>
</target>
<!-- remove generated files -->
<target name="clean" description="remove generated files">
<delete dir="${dir.build}"/>
<delete dir="${dir.dist}"/>
</target>
<!-- compile source code -->
<target name="compile" depends="init" description="compile source code">
<javac destdir="${dir.build}" >
<src path="${dir.src}"/>
<classpath refid="classpath"/>
</javac>
</target>
<!-- create distribution archive -->
<target name="dist" depends="compile" description="create distribution archive">
<jar jarfile="${dir.dist}/${ant.project.name}.jar"
basedir="${dir.build}"
includes="**/*.class">
</target>
</project>
If this build script was used to build the ATM application then the output result would look similar to the following:
>ant -f atm.xml clean
Buildfile: atm.xml
clean:
BUILD SUCCESSFUL
Total time: 0 seconds
>ant -f atm.xml
Buildfile atm.xml
init:
[mkdir] Created dir:C:\Build\ATM\build
[mkdir] Created dir:C:\Build\ATM\dist
compile:
[javac] Compiling 4 source files to C:\Build\ATM\build
BUILD SUCCESSFUL
Total Time: 4 seconds
In this build script a Java archive called atm.jar is being built. There are four targets: init, clean, compile and dist. Sometimes a target will have a dependency on another target, for example before you create a distribution (.jar) file, you would need to compile the source code. These dependencies are easily specified via a depends attribute in the target. You can see this with the dist target on line 40 (where the target requires the compile target to be executed first). Ant will automatically execute any dependencies.
You will see that on lines 4-7 the script makes reference to property values. In Ant, properties are equivalent to most programming language's concept of variable constants; that is to say they are immutable and once properties have been assigned a value they cannot be changed.Here they are being used to define directory names. You make references to properties by using the ${property_name} symbols (see line 11 for an example). An interesting feature of properties is that they can be overridden from the command line. For example, if you wanted to override the dir.build property, you could use the following:
>ant -f atm.xml compile -Ddir.build=bin
If you are compiling source code in Java you will need to define a classpath.This is the combination of libraries containing pre-built classes, that you need to build against. In lines 10-16 a classpath is defined which looks at the build directory as well as a set of third party .jar files held at the location C:\JavaTools\lib.
One final point worthy of note is the use of Ant's built in variables. In this example, on line 40 we are using the ${ant.project.name} variable when creating a jar file, this refers to the project name atmas defined in line 3, so the name of jar file will be atm.jar.
Summary
This article was intended as a rapid introduction to some of Ant's capabilities. Ant is a powerful but sometimes complex tool. It is relatively easy to get started using Ant and there are many tutorials and examples available on the Internet. However, Ant can become quite complex for large projects andtherefore there are a number of good practices, such as creating reuseable macros and libraries that can be implemented to make Ant more practical in such environments. For more information on how to achieve this, refer to the references given below.
References
- Ant in Action
- Apache Ant - The Buildmeister's Guide, Second Edition
- IBM Rational(R) ClearCase(R), Ant, and CruiseControl: The Java(TM) Developer's Guide to Accelerating and Automating the Build Process
- Ant: The Definitive Guide, 2nd Edition
- ANT: The Java Build Tool In Practice (Programming Series)
- Ant Developer's Handbook
- Apache Ant home page
- The Ant manual
- Top 15 Ant Best Practices
- Apache Ant Best Practices (Book Excerpt)
