3.2 Writing a Basic Buildfile

3.2.1 Problem

You want to write a basic Ant buildfile.

3.2.2 Solution

Example 3-1 lists a simple Ant buildfile that you may use as a boilerplate for your own projects.

Example 3-1. Boilerplate Ant buildfile
<?xml version="1.0"?>
<project name="Template Buildfile" default="compile" basedir=".">
  <property name="dir.src" value="src"/>
  <property name="dir.build" value="build"/>
  <property name="dir.dist" value="dist"/>

  <!-- Creates the output directories -->
  <target name="prepare">
    <mkdir dir="${dir.build}"/>
    <mkdir dir="${dir.dist}"/>
  </target>

  <target name="clean"
          description="Remove all generated files.">
    <delete dir="${dir.build}"/>
    <delete dir="${dir.dist}"/>
  </target>

  <target name="compile" depends="prepare"
          description="Compile all source code.">
    <javac srcdir="${dir.src}" destdir="${dir.build}"/>
  </target>

  <target name="jar" depends="compile"
          description="Generates oreilly.jar in the 'dist' directory.">
    <jar jarfile="${dir.dist}/oreilly.jar" 
         basedir="${dir.build}"/>
  </target>
</project>

3.2.3 Discussion

You generally call this file build.xml, and can put it anywhere you like. In our example, the buildfile is found in the directory containing the src directory. The <project> tag is found in all buildfiles:

<project name="Template Buildfile" default="compile" basedir=".">

The project name should be something descriptive, as this may show up when you run Ant from other tools. The default attribute specifies which target is invoked when the user types ant. Finally, the basedir attribute specifies the directory from which all paths are relative to. Regardless of where you invoke Ant, "." is the directory containing the buildfile.

Although you can put build.xml anywhere, we encounter the fewest difficulties when it is placed at the root of the project tree.

To invoke other targets, you type something like ant jar or ant clean compile. If the buildfile were called myproj.xml, you would type ant -buildfile myproj.xml clean.

The remainder of our buildfile consists of tasks and targets. The end user invokes targets by name; tasks perform the actual work. The property task, for example, defines name/value pairs to avoid hardcoding throughout the buildfile:

<property name="dir.src" value="src"/>

The prepare target is a convention used in nearly every buildfile:

<target name="prepare">
  <mkdir dir="${dir.build}"/>
  <mkdir dir="${dir.dist}"/>
</target>

This creates the output directories relative to the project's base directory. If the directories already exist, the mkdir task ignores the request. Our example shows how the prepare target comes into action via target dependencies:

<target name="compile" depends="prepare"
        description="Compile all source code.">
  <javac srcdir="${dir.src}" destdir="${dir.build}"/>
</target>

Since the compile target depends on prepare, the output directories are always created before the compiler runs. Like other Ant tasks, the javac task only performs work if it has to. In this case, it only compiles .java files that are newer than their corresponding .class files.

It is important to note that checking timestamps on files results in fast builds, but does not catch logical dependencies between files. For instance, changing methods in a base class will not trigger a recompile on derived classes. For this reason, it is a good idea to type ant clean compile frequently. If you are using a version control tool like CVS, perform a clean compile just before checking in code so you don't "break the build" for other developers.

3.2.4 See Also

Ant ships with an optional task called depend that calculates dependencies based on references found inside of .class files, rather than merely checking file timestamps. You might also want to consider using IBM's Jikes compiler, since it is generally considered to be faster than Sun's javac compiler and it can provide better errors and warnings. See the Ant documentation for the javac task to learn how to use Jikes with Ant.