Ant Script Library Design Principles

Overview

The design of the Ant Script Library (ASL) is based on a number of principles. It helps to understand what these are, as it makes it easier to follow what they do, and how to use these principles in other scripts.

Orthogonal Modules

The ASL is composed of a number of files, each containing a relatively small number of targets. The targets are named in relatively generic terms. The purpose is to allow alternate scripts to be imported if a different implementation is required. For example, if you like to use Apache Ivy to manage your dependencies in a repository, you can import the Ivy targets as follows:

<import file="ant-script-library/asl-repo-ivy.xml"/>

This import will then make the following targets available in your script: repo-cleancache, repo-report, repo-resolve, repo-retrieve.

If you later decided that you didn’t want to use Ivy, but rather the Maven Ant Tasks instead, you could replace the previous import with the following:

<import file="ant-script-library/asl-repo-maven.xml"/>

With this one change, your build script then changes to use a completely different repository management tool. Because this different module provides targets with the same names, no other changes would be required in the script (though in this case, you would have to replace the ivy.xml file with an equivalent pom.xml).

Small Targets

Each ASL module is composed a number of top level targets public targets (these have descriptions, and so are described when you type `ant -p`), as well as a number of private targets (these are prefixed with a '-' to ensure that they can’t accidentally be invoked from the command line). Looking over the scripts, you will not that no target is more than 5 - 10 lines long, and does at most one or two tasks. The are a number of reasons for this:

Convention Over Configuration

The ASL has a number of built in configuration defaults, such as the location of the source directory, the location of the test source directory, and so on. If your application conforms to these expected default, your build script can become incredibly simple. The simplest possible script might be:

<project name="my-project" default="dist">
  <import file="ant-script-library/asl-java.xml"/>
</project>

In general, the ASL scripts tend to expect your project conforms to the Maven standard directory layout.

Configuration Over Overriding

Not everyone has their project laid out in exactly the way, and it’s not always easy to change this. In these cases, it’s usually just a matter of defining specific properties with the actual values for your project before importing the ASL scripts. For example:

<project name="my-project" default="dist">
  <property name="java-build.src-dir" location="src"/>
  <property name="java-test.src-dir" location="test"/>
  <import file="ant-script-library/asl-java.xml"/>
</project>

The properties that can be set to control the behaviour are documented on the reference pages (or just look inside the library scripts themselves).

Overriding Over Reimplementation

In cases where you need to do something complete different to what the ASL scripts are doing, you can override specific targets in the top level build script. Just those targets will be overridden, and everything will work without change. For example:

<project name="my-project" default="dist">
  <import file="ant-script-library/asl-java.xml"/>

  <!-- *******************************************
  * target override: copy-resources
  ******************************************** -->
  <target name="copy-resources"
      depends="asl-java-build.copy-resources"
      description="Copies resources in preparation to be packaged">
    <copy todir="${java-build.classes-dir}">
      <fileset dir="resources"/>
    </copy>
  </target>
</project>

In this case, the copy-resources target from the module asl-java-build is being overridden. Note that the new target still has a dependency to the original target of that name, meaning that both the original and this new target will be called. Using this technique, any target can become an extension point. The alternative is to not declare a dependency on the original target, in which case the new copy-resources target completely replaces the original.


Is there a problem or mistake on this page? Do you want to contribute some changes? Send me an email at joe@exubero.com.