Today
we will learn about the basics of ant . For those who are new to Ant tool ,this
entry will help them to move forward.Here aim using my Eclipse 7.5 [ we will
use the in build ant for this.
Ant is
a java based build tool . According to the author of ant tool , the acronym is
"another neat tool". Build tools are mostly used in software
Development to transform source code and other input files into an executable
form. Traditional projects in c and c++ use make tool in Unix which performs the build invoking shell commands. Ant is also similar to make but instead of
invoking platform specific shell commands , it uses cross platform java
classes. The build file is in xml format .lets see how we can write build files
,
Now
lets write a basic build file ,
<project
basedir="." default="" name="basicBuild">
<echo>this
is a basic build</echo>
</project>
So for
every build file in ant ,we will have a project element. In the above build
file I specified the echo which displays a message at runtime .
Now
lets move to more complex examples,
Project
& Target :The project element contain target elements. A target element
defines a set of tasks , that we want to execute . We can tell ant as to which
target to execute when no default is defined. The top level element project
needs to have some attributes like
default
: says which target to execute by default .
basedir
: the path to the directory that ant should use when working paths . [.]refers
to the current working directory that build file is in.
Below
is the example which explains the project and target elements ,
<project
basedir="." default="compile"
name="basicBuild">
<target
name="compile">
<echo>This
is the basic echo</echo>
<description>Basic
Build</description>
</target>
</project>
We have
defined a default target which is "compile" . we also provided a
basic description for the target.
Properties
: properties in ant are like programming variables which has a property and
value assigned to it. However like in other programming languages , a value for
a variable is set only once [ much like mutable ] .here is a sample example as
to how to use a property and how to access the property value
<project
basedir="." default="compile"
name="basicBuild">
<property
name="name" value="Jagadish" ></property>
<target
name="compile">
<echo>This
is the basic echo</echo>
<description>Basic
Build</description>
<echo>${name}</echo>
</target>
</project>
You can
see , we will be using the Unix style of accessing the variable value. there
are number of predefined propertied in ant. The system properties set by the
java environment are available as a ant properties . Meanwhile ant also sets
some of the properties like ant version which can be accessed.
Properties
are also used to define the files paths and directory paths , but this could
cause problems across different platforms with different path separators . Ant
provides a location attribute which holds the path in platform neutral way.
Defining
Dependencies : in a more complex build , there may be many tasks to perform
like compiling the java class ,making a jar file of them , compressing them
e.t.c . Many of the task in ant will be having a specific order like we cannot
build a jar when we did not compile the class. So the order is to compile the
classes first and then making a jar with them.
Ant
provides a flexible way of handling these dependencies . It provides a
"depends" attribute to a target such that when we define the depends
attribute , the target which is specified in depends attribute is executed
first then the current one ,
<project
basedir="." default="compile"
name="basicBuild">
<property
name="name" value="Jagadish" ></property>
<property
name="sub-Name"
value="${name}.manchala"></property>
<target
name="compile" depends="build">
<echo>This
is the basic echo</echo>
<description>Basic
Build</description>
<echo>$
{name}</echo>
<echo>${sub-Name}</echo>
</target>
<target
name="build">
<echo>This
is the basic build</echo>
</target>
</project>
In the
above code , the target with name build is executed first and then the target
with name compile is executed.
An ant
is primarily a build tool and it provides an excellent support for invoking the
java related tasks.consider the javac element
<project
basedir="." default="compile"
name="basicBuild">
<property
name="name" value="Jagadish" ></property>
<property
name="sub-Name" value="${name}.manchala"></property>
<target
name="compile" depends="build">
<echo>This
is the basic echo</echo>
<description>Basic
Build</description>
<echo>$
{name}</echo>
<echo>$
{sub-Name}</echo>
</target>
<target
name="build">
<property
name="createDir" value="com.myCompany.classes"></property>
<echo>This
is the basic build</echo>
<mkdir
dir="$ {createDir}"/>
<javac
srcdir="." destdir="${createDir}"></javac>
</target>
</project>
In the
above code we have used the basic javac Command to compile all the java files
that are in src directory and place them in the new directory that we created
using the mkdir element. there are some attributes for the javac command that
may be very useful like
classpath
: much like adding -classpath to javac command
debug :
provides the debug information .
An
important thing is that ant does not compile classes that are already compiled
if their time stamp value doesn't changes .so it is a good practice to clean
the compiled classes first and then build. As we know that ant is implemented
itself in java , the jvm in which ant is currently running invokes the javac
for compiling the classes in the same jvm which gives us more performance while
building projects.
In some
cases we need to invoke a new compiler separately in such cases use the fork
attribute of the java element . And if we need to specify a javac executable
and pass some memory setting we can do that as ,
<javac
executable="c:/java/bin/javac"
memorymaximumsize="128M"></javac>
Creating
Jar : creating jar in ant is very simple. It provides a basic jar element which
does the work .
<jar
destfile="pack.jar" basedir="."></jar>
I just
created a jar file named "pack.jar" with the current directory.as we
know for every jar file we will have a manifest file . Ant provides support to
include a basic manifest file in the jar.the contents of the manifest file can
be specified by using the manifest element as ,
<jar
destfile="pack.jar" basedir=".">
<manifest>
<attribute
name="Build-By" value="jagadish"/>
</manifest>
</jar>
Time
Stamping Builds : It is often necessary to build the environment with time and
date. The tstamp element in ant provides with options to includes date and time
.the timestamp does not produce any output generally but it puts value to 3
properties which can used.
The 3
properties include ,
DSTAMP
: current date
TSTAMP
: current time
TODAY :
today date in string format
So we
can use this as
<target
name="build">
<property
name="createDir"
value="com.myCompany.classes"></property>
<echo>This
is the basic build</echo>
<mkdir
dir="$
{createDir}"/>
<javac
srcdir="." destdir="${createDir}"></javac>
<tstamp/>
<jar
destfile="pack-$ {DSTAMP}.jar" basedir=".">
<manifest>
<attribute
name="Build-By" value="jagadish"/>
</manifest>
</jar>
</target>
The
tstamp can be used to set different properties like current time zone e.t.c by
using a format element.
File
System Operations : in this section , we will work on file operations including
creating , deleting of directories e.t.c
Creating
Directory :
<property
name="createDir"
value="com.myCompany.classes"></property>
<mkdir
dir="${createDir}"/>
Deleting
a Directory :
<property
name="createDir"
value="com.myCompany.classes"></property>
<delete
dir="${createDir}"></delete>
Copying
a file:
<copy
file="./BasicBuild.java"
tofile="./BasicBuildTestCopy.java"/>
Moving
a file :
<move
file="./BasicBuild.java"
tofile="./BasicBuildTestCopy.java"/>
We can
also move and copy files from one directory to other directory.
Creating
Zip and Unzip : ant provides options for zipping and unzipping . This is much
similar as creating a jar file.
<zip
destfile="basic.zip" basedir="." ></zip>
We have
facilities for creating zip , gzip ,bzip2 and tar.
Replacing
Tokens: the last file operation is replacing tokens , in this the token that is
to be replaced is searched from the file and replaced with the new value , as
<replace
file="nothing.txt" token="old"
value="new"></replace>
Pattern
Matching : in the previous file operations , we have seen that we perform tasks
on individual files and directories , but there are situations where we need to
perform operations on a group like compiling a group of java classes e.t.c. in
such cases pattern matching will be useful. Pattern matching is done by using
wild cards , * which matches zero or more characters and ? Which matches
exactly one character. The pattern to match all files of java is *.java .
matching
is also performed on directories , a pattern with src*/.java says to include
java files in directories with prefix src .there is a another pattern construct
** which includes all directories , */.java matches all java files in all
directories. This construct includes all the names with String "test"
in them */test.These patterns are used in include and exclude elements.
directory
Sets: directory set are used to select directories based on the pattern .the
element "dirset" is used for this case ,starting from the base
directory.
File
Sets : file sets are used to define a set of files .this is done by selecting
the directory first in which the files occur.
Execution
Tasks : we have a facility in ant to run a program as an executable task , as
<exec
executable="notepad.exe"></exec>
Using
Selectors : a file set is used to specify a group of files , and contents of
this group can be used with include and exclude elements. We can also use
selectors with include and exclude elements to select files .
Here is
a list of core selectors available with ant ,
Size :
this attribute is used to select files based on their sizes. The default unit
is bytes . We can use when attribute to specify nature of comparison like less
,more e.t.c.
Contains
: use this to select files that contains a given text.
Filename
: this helps to get files based on the file name.
Date :
to select files based on the date parameter , like last Modified e.t.c.
Present
: selects files with the same name in the directory specified .
These
are some of the core selectors , we can dig for more of them and their usages.
Chaining
Builds : in a normal large projects , there exists more that one build file .
In such a cases to run all the build files would be a time consuming . We have
a facility in ant which allows us to chain 2 or more build files.we can call
ant file as ,
<ant
antfile="secondBuild.xml" target="showMsg"
inheritall="false"/>
Here is
a sample snippet codes ,
secondBuild.xml:
<project
basedir="." default="">
<target
name="showMsg">
<echo>This
is my Seo=cond Build File</echo>
</target>
</project>
Build.xml:
<project
basedir="." default="compile"
name="basicBuild">
<target
name="compile">
<ant
antfile="secondBuild.xml" target="showMsg"
inheritall="false"/>
<echo>This
ismy first build file</echo>
</target>
</project>
We have
a point to consider here , the properties that are set in the parent ant file
are inherited to the ant files that are included. In such case we need to set
the attribute inheritall="false".
Targets
Based On Condition : we can use a condition in ant in order to perform a
condition based logic. Here is a simple condition operation ,
<project
basedir="." default="do-windows"
name="basicBuild">
<target
name="do-windows" if="is.windows">
<echo>This
is windows</echo>
</target>
<condition
property="is.windows">
<os
family="windows"/>
</condition>
</project>
Custom
Ant Tasks : even though we write tasks that perform various operations , there
may be some times we need to write our own ant tasks which performs some
validations or complex post build verification checks .in that case ant
provides a way to write our own ant tasks .
let's
see how we can write our own ant tasks, we need
create
a java class that subclass org.apache.tools.ant.Task class and overrides the
execute method
packaging
your class files into a jar file [ optional ]
register
the custom task in the ant build file using the taskdef element.
lets
write a simple helloWorld custom ant task , in this custom task we will write a
log message to the standard output console .
lets
start with the code ,
public
class CustomAnt extends Task {
public
void execute() throws BuildException {
System.out.println("We
R In The Custom Defined Ant Task");
}
}
now we
will write a antTasks.properties file which holds the keys as ,
customant=com.prokarma.CustomAnt
save
that in a file and now create a jar file named sample.jar with files
CustomAnt.java and antTasks.properties.
now our
ant build files looks as ,
<project
name="SimpleJavaPro" default="compile"
basedir=".">
<description>This
is jagadesh</description>
<echo>This
is jagadesh in here</echo>
<taskdef
resource="antTasks.properties"
classpath="sample.jar"></taskdef>
<target
name="compile">
<customant/>
</target>
</project>
we can
just run the ant file and see the output .
let
move to a more advanced level of creating custom ant tasks where we provide a
user input value on which the response will be shown depending on the value
sent .
here is
the code for customAnt.java
public
class CustomAnt extends Task {
private
String myName="";
public
CustomAnt() {
// TODO
Auto-generated constructor stub
}
public
String getMyName() {
return
myName;
}
public
void setMyName(String myName) {
this.myName
= myName;
}
public
void execute() throws BuildException {
if(this.myName.equalsIgnoreCase("jagadesh")){
System.out.println("the
Name Passed Is Wrong");
}else
if(this.myName.equalsIgnoreCase("jagadish")){
System.out.println("the
Name Passed Is Right");
}
}
}
I added
a private String variable which will be checked for a perticular string
depending on the value sent through the ant build file .
we have
no changes in the antTasks.properties file but in the ant build file we need
add a attribute to the customAnt element as follows ,
<project
name="SimpleJavaPro" default="compile"
basedir=".">
<description>This
is jagadesh</description>
<echo>This
is jagadesh in here</echo>
<taskdef
resource="antTasks.properties"
classpath="sample.jar"></taskdef>
<target
name="compile">
<customant
myName="jagadish"/>
</target>
</project>
pass
jagadish as a value to myName and you will that the name passed it right or it
will say the name passed is wrong.
Hence
this completes the Ant basics . hope this helped you,