Introduction to the Ant Script Library
This article is about learning to build your software using
Ant. Writing a new
build.xml
file from scratch can be difficult, especially
if you are not very familiar with Ant. To make this easier, I have written
some reuseable libraries that I will show in my examples below. The
libraries are free and you can find documentation and a downloadable zip from
the website at http://www.exubero.com/asl/.
Example Project: Deep Thought
For the purposes of this example, suppose you are developing code for an AI project called Deep Thought. You've been developing the code in an IDE, but are now looking build the code using Ant.
The project structure currently looks like this:
%tree . `-- src `-- example `-- DeepThought.java
Install the Ant Script Library
The first thing to do is grab a copy of the Ant Script Library, which can be retrieved from http://www.exubero.com/asl/download.html. Download and unzip the file into a subdirectory of your project.
Build the Code
Create a new file called build.xml
in the top level directory
of the project, with the following contents:
<project name="DeepThought" default="dist">
<property name="java-build.src-dir" location="src"/>
<import file="ant-script-library/asl-java-build.xml"/>
</project>
Because the directory containing the source code is not exactly as
expected by the Ant Script Library, we have to override the
default location by setting the property java-build.src-dir
before importing the Java build module from the Ant Script Library. The
line <import file="ant-script-library/asl-java-build.xml"/>
does the work of making all the build targets available to your script.
The project structure now looks like this:
%tree . |-- build.xml |-- ant-script-library | |-- asl-java-build.xml | `-- asl-java-test.xml `-- src `-- example `-- DeepThought.java
With only four lines of Ant build, what can our script do? Looking at the project help is a good first place to look:
%ant -p Buildfile: build.xml Main targets: clean Deletes files generated by the build compile Compiles the java source copy-resources Copies resources in preparation to be packaged in jar dist Create a distributable for this java project generate Generates source code jar Create a jar for this java project Default target: dist
Not bad! We can compile the code, and package the compiled code into a
jar file. The default dist
target does all this:
%ant dist Buildfile: build.xml generate: -init-classpath: compile: [mkdir] Created dir: /workspace/deepthought/target/classes [javac] Compiling 1 source file to /workspace/deepthought/target/classes copy-resources: -init-time: -init-jar-classpath: jar: [mkdir] Created dir: /workspace/deepthought/target/dist [jar] Building jar: /workspace/deepthought/target/dist/DeepThought.jar dist: BUILD SUCCESSFUL Total time: 1 second
From the BUILD SUCCESSFUL
message, we can see that the build
worked. All files created by the build are put into a subdirectory called
target
. This includes generated class files, and any other
artifact from the build. The file we can distribute to users of our application
has been created in target/dist/DeepThought.jar
.
Test the Code
Now that the distributable jar
file has been created, we can
run some unit tests against it. In this case we'll be using
JUnit. It's good practice to put unit
tests in a parallel directory structure to the source code. With this in mind,
we can create a test case in the file test/example/DeepThoughtTest.java
.
We will also need a copy of the junit.jar
library. If we put this
in a directory called "lib
", it will be automatically picked
up by the build. This gives us a directory layout like this:
%tree . |-- build.xml |-- ant-script-library | |-- asl-java-build.xml | `-- asl-java-test.xml |-- lib | `-- junit.jar |-- src | `-- example | `-- DeepThought.java `-- test `-- example `-- DeepThoughtTest.java
There's one final change: we need to tell our build.xml
that
it needs to import the testing targets from the library file
asl-java-test.xml
. Edit build.xml
so that it
looks like this:
<project name="DeepThought" 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-build.xml"/>
<import file="ant-script-library/asl-java-test.xml"/>
</project>
With this change, there are now a number of new test related targets available from our build:
%ant -p Buildfile: build.xml Main targets: clean Deletes files generated by the build compile Compiles the java source copy-resources Copies resources in preparation to be packaged in jar dist Create a distributable for this java project generate Generates source code jar Create a jar for this java project test-all Runs all tests test-integration Runs integration tests test-run-integration Runs the integration tests test-run-unit Runs the unit tests test-unit Runs unit tests Default target: dist
The test-all
target looks like a good candidate. Here's how
to run that target from the command line:
%ant test-all (output truncated) -test-init-classpath: -test-compile: [mkdir] Created dir: /workspace/deepthought/deepthought/target/test-classes [javac] Compiling 1 source file to /workspace/deepthought/deepthought/target/test-classes -test-copy-resources: -test-init-cobertura: -test-instrument: [cobertura-instrument] Cobertura 1.9 - GNU GPL License (NO WARRANTY) - See COPYRIGHT file [cobertura-instrument] Instrumenting 1 file to /workspace/deepthought/deepthought/target/instrumented-classes [cobertura-instrument] Cobertura: Saved information on 1 classes. [cobertura-instrument] Instrument time: 149ms -test-prepare: -test-init-fileset-unit: test-run-unit: [mkdir] Created dir: /workspace/deepthought/deepthought/target/test-data [junit] Testsuite: example.DeepThoughtTest [junit] Tests run: 1, Failures: 0, Errors: 0, Time elapsed: 0.157 sec [junit] [junit] Cobertura: Loaded information on 1 classes. [junit] Cobertura: Saved information on 1 classes. -test-init-fileset-integration: test-run-integration: test-all: BUILD SUCCESSFUL Total time: 5 seconds
There's a lot more output this time. However, the final message from
Ant is BUILD SUCCESSFUL
, and we can see earlier in the output
that our tests were run successfully:
[junit] Testsuite: example.DeepThoughtTest [junit] Tests run: 1, Failures: 0, Errors: 0, Time elapsed: 0.157 sec
That's it! We have a complete compile, package and test build up and
running, with only a relatively small build.xml
and the Ant
Script Library. The build.xml
could have been smaller again
if we had followed the expected directory layout, and so we would not have
to explicitly define the src
and test
directories.
The Ant Script Library has many more features than shown here, including reporting on code metrics, dependency management, SCM integration and software release targets. Refer to the documentation at http://www.exubero.com/asl/ for more details.
Is there a problem or mistake on this page? Do you want to contribute some changes? Send me an email at joe@exubero.com.