Introduction
Ant is a
Java-base builds tool. According to James Duncan Davidson (ANT author) ANT is an Another Neat Tool.
Later the term ANT synchronized with real ant (nature
creature ant) to see ant’s capability and strength. An ant can carry a weight
dozens of times of its own. Thus we can understand that ant is a java base
building tool that works multiple times more to its real power. ANT works just
the “make” tool that works for C and C++. Using ANT we can make a numerous tasks
without any customization. This document contains explanation on each task in
more details step-by-step when it requires. To understand this document, I
shall go step-by-step, starting from installation of ANT binary.
ANT
Installation
This
document is prepared under this assumption that the reader of this document has
knowledge about system variables, environment variables and installation and
configuration of software. Steps for ANT installation is –
To get up and running with the binary edition of
Ant quickly, follow these steps:
1.
Make
sure you have a Java environment installed. To get latest JAVA click hit this
link - http://www.oracle.com/technetwork/java/javase/downloads/index.html.
If JDK is not present, only the JRE runtime, then many tasks will not work. Ant
1.8.* works with JDK 1.4 but strongly recommended JDK 1.5. So first be sure
that machine must have JDK 1.5 or later environment.
3.
Uncompress
the downloaded file into a directory.
4.
Set
environmental variables
JAVA_HOME
to your Java environment, ANT_HOME
to the directory you
uncompressed Ant to, and add ${ANT_HOME}/bin
(in UNIX environment) or %ANT_HOME%/bin
(Windows) to your PATH
.
5.
Optionally,
from the
ANT_HOME
directory run ant -f fetch.xml -Ddest=system
to get the library dependencies
of most of the Ant tasks that require them. If you don't do this, many of the
dependent Ant tasks will not be available.
Once you completed above steps, then open command
prompt and run the following commands –
C:\>set path=”c:apache-ant-1.8.1\bin”; %path%
C :\> ant -version
C:\>set path=”c:apache-ant-1.8.1\bin”; %path%
C :\> ant -version
If both command run properly that means
you have configured Another Neat Tool (ANT). And to seeing this screen means your
installation phase has over.
Note: Ant 1.8.* works with
jdk1.4 and higher, Ant 1.7.* works with JDK.3 and higher, Ant 1.6.* works with JDK
1.2 and higher, Ant 1.2 to Ant 1.5.* work with JDK 1.1 and higher.
ANT
Basics
After successful installation of ANT
version 1.8.1, now I move on to some core or basics of ant. An ant build file comes in the form of an XML
documents, all that is required is a simple text editor to edit the build
file(s). An editor that provides XML syntax supportive utility is more suitable
and preferable. The ant installation comes with a JAXP-compliant XML parser,
this means that the installation of an external XML parser is not necessary. Details
about “build.xml” file … Following build.xml are well formatted xml file that
comprised of several target entities. There a lot to explain about the
following build.xml file.
First Line of the build.xml is –
xml version="1.0"?>
Since Ant build files are XML
files the document begins with an XML declaration which specifies which version
of XML is in use, this is to allow for the possibility of automatic version
recognition should it become necessary. Next lien of this document is project
element.
Project Element
Every build file must
have least project and target (default) elements. Above build file has also a
project element. Project element has an optionally a description for the
project can be provided as a top-level
element. Each project defines one or more targets. A target is a set of tasks
you want to be executed. When starting Ant, you can select which target(s) you
want to have executed. When no target is given, the project's default is used.
In following table describe the attribute of project element –
Attribute
|
Description
|
Required
|
name
|
the
name of the project.
|
No
|
default
|
the
default target to use when no target is supplied.
|
No;
however, since Ant 1.6.0, every project includes an implicit target
that contains any and all top-level tasks and/or types. This target will
always be executed as part of the project's initialization, even when Ant is
run with the -projecthelp option.
|
basedir
|
the
base directory from which all path calculations are done. This attribute
might be overridden by setting the "basedir" property beforehand.
When this is done, it must be omitted in the project tag. If neither the
attribute nor the property has been set, the parent directory of the
buildfile will be used.
|
No
|
Target Element
Next element of this
file is target –
The target element is used as a
wrapper for sequences of actions. A target has a name, so that it can be
referenced from elsewhere, either externally from the command line, or
internally via the depends keyword, or through a direct call. The target
in the example is called "init" (initiate), it makes a directory
using the mkdir element with the name specified by the build property
defined in three. The target element has a number of possible attributes,
unless otherwise specified, these are optional:
Attribute
|
Description
|
Required
|
name
|
The name of the target is used
to reference it from elsewhere, it is subject to the constraints of XML well
formed-ness.
|
Yes
|
depends
|
This is a comma separated list
of all the targets on which this target depends, for example, immediate next
block illustrates how compile depends on init, in other words,
depends contains the list of the targets that must be executed prior to
executing this target.
|
No
|
if
|
This is a useful attribute
which allows one to add a conditional attribute to a target based on the
value of a property for example, if="gui-ready" could be
used to only execute the encapsulating target's instructions if the property gui-ready
was is (to any value).
|
No
|
unless
|
This is the converse of if,
for example, unless="gui-ready" could be used to
conditionally execute the contents of the encapsulating target. The targets'
contents will be executed unless the the property gui-ready is
set (to any value).
|
No
|
description
|
This is a short description of
the target.
|
No
|
extensionOf
|
Adds the current target to the depend list of the
named extension-point. Since Ant 1.8.0.
|
No
|
onMissingExtensionPoint
|
What to do if this target tries
to extend a missing extension-point. ("fail", "warn",
"ignore"). Since Ant 1.8.2.
|
No.
Not allowed unless
extensionOf
is present. Defaults to fail . |
Target
element has a attribute name depends, following example are concerning this
attribute –
As explained in above block,
depends allows one to specify other targets that must be executed prior to the
execution of this target. In the listing above depends="init" is
used to indicate that the compile target requires that the target named init
be executed prior to executing the body of compile. For more details
about target just visit this link http://ant.apache.org/manual/targets.html.
Property Element
In given
example build file there is an element name property. For example you may see
the following snippet of build.xml file –
<property name="sourceDir" value="src"
/>
<property name="outputDir" value="classes"
/>
<property name="deployJSP" value="/web/deploy/jsp"
/>
<property name="deployProperties" value="/web/deploy/conf" />
Properties are an important way to customize a build process or to just
provide shortcuts for strings that are used repeatedly inside a build file.In its most simple form properties are defined in the build file (for example by the property task) or might be set outside Ant. A property has a name and a value; the name is case-sensitive. Properties may be used in the value of task attributes or in the nested text of tasks that support them. This is done by placing the property name between "
${
"
and "}
" in the
attribute value. For example, if there is a "builddir" property with
the value "build", then this could be used in an attribute like this:
${builddir}/classes
. This is
resolved at run-time as build/classes
.Normally property values cannot be changed, once a property is set, most tasks will not allow its value to be modified. In general properties are of global scope, i.e. once they have been defined they are available for any task or target invoked subsequently - it is not possible to set a property in a child build process created via the ant, antcall or subant tasks and make it available to the calling build process, though, with Ant 1.8.0 property expansion has become much more powerful than simple key value pairs, more details can be found from here http://ant.apache.org/manual/properties.html. Ant provides access to all system properties as if they had been defined using a
task. For
example, ${os.name}
expands
to the name of the operating system. Some built-in properties are –
Task Element
A task is
a piece of code that can be executed. A task can have multiple attributes (or
arguments, if we prefer). The value of an attribute might contain references to
a property. These references will be resolved before the task is executed. Tasks
have a common structure:
<name attribute1="value1" attribute2="value2" ... />
Where name is the name of the task, attributeN is the
attribute name, and valueN is the value for this attribute. All tasks share a
task name attribute. The value of this attribute will be used in the logging
messages generated by Ant. Tasks can be assigned an id attribute:
<taskname id="taskID"
... />
Where taskname is the name of the task,
and taskID is a unique identifier for this task. For understanding I am
giving the snippet code from given example –
The javac element, as used
above, is a task, tasks are performed in the body of a target, in
this case, the source directory is specified by referencing the src property
and the destination directory is specified by referencing the build property.
The example above causes javac to be executed, compiling all the .java
files in the directory specified by the src property and placing the
resultant .class files in the directory specified by the build property.
These are a set of built-in tasks, but it is also very easy to write your own.
To write your own task visits this link - http://ant.apache.org/manual/develop.html
Tasks
|
Description
|
ant
|
Used to execute
another ant process from within the current one.
|
copydir
|
Used to copy an entire
directory.
|
copyfile
|
Used to copy a single
file.
|
cvs
|
Handles
packages/modules retrieved from a CVS repository.
|
delete
|
Deletes either a single
file or all files in a specified directory and its sub-directories.
|
deltree
|
Deletes a directory
with all its files and subdirectories.
|
exec
|
Executes a system
command. When the os attribute is specified, then the command is only
executed when Ant is run on one of the specified operating systems.
|
get
|
Gets a file from an
URL.
|
jar
|
Jars a set of files.
|
java
|
Executes a Java class
within the running (Ant) VM or forks another VM if specified.
|
javac
|
Compiles a source tree
within the running (Ant) VM.
|
javadoc/javadoc2
|
Generates code
documentation using the javadoc tool.
|
mkdir
|
Makes a directory.
|
property
|
Sets a property (by
name and value), or set of properties (from file or resource) in the project.
|
rmic
|
Runs the rmic compiler
for a certain class.
|
tstamp
|
Sets the DSTAMP,
TSTAMP, and TODAY properties in the current project.
|
style
|
Processes a set of
documents via XSLT.
|
These
are the some basic elements about ant build.xml file. You can learn in depth by
visiting this link - http://ant.apache.org/manual/index.html. Now I am going to make a sample project using build.xml…
A Typical project as an Example
The
purpose of this section is to make a project using ant and its build.xml file. Steps
that I shall follow are –
1. 1. Preparing directory structure.
2. 2.Creating source file in standard
directory location (recommended by ant)
3. 3. Building build.xml file.
4. 4. Execute ant command.
1. Preparing
directory structure -
It is good idea to adhere the ant
recommendation because we will use the ant as a building tool. According to ant
recommendation we shall create a root directory inside this we will create
following directory structure:
1.1 src: For project source files.
1.2 build: For compiled/output files
produced (by Ant).
1.3 lib : For class libraries and
dependency files.
Create an “Application” directory
and from within this, create the three directories described above. A simple
Java program will be used to illustrate the use of Ant.
2. Source File
inside directory src -
Copy following code and paste in java
compatible editor, this is not mandatory you may even a simple editor also. Save
this file inside src folder using same package hierarchy which is mention as
package statements with name “HelloWorld.java”.
package
com.greensoft.ant.example;
/**
* @author Pravind Kumar
*
*/
public
class HelloWorld {
/**
* Default Constructor
*/
public HelloWorld() {
}
/**
* @param args
*/
public static void main(String[]
args) {
System.out.println("Hello
World By Pravind Kumar");
}
}
3. Building
build.xml -
This
is a standard build.xml file, just copy and pastes it in an editor and saves as
“build.xml” in parallel to src folder.
4. Execute ant
Command -
1. Open run command with combination
of window key + r.
2. Type cmd and press Enter key.
3. On command prompt type cd\ and
press enter
4. Now go to your “Application”
folder
5. Type ant and press enter…. WOW!
Your result on you console. And look like this…
Ant File Sets
A FileSet is a filter which uses one or more
patterns to specify which files are desired. A FileList is a list of
desired files. FileSets use PatternSets and Patterns to
define their actions.
•
?
is used to match
any character.
•
*
is used to match zero or more characters.
•
**
is used to match
zero or more directories.
A FileSet must specify a base directory from
which all other path calculations are made; this is supplied via the dir attribute.
Fileset has a various attribute;
following tables dictate about fileset attribute –
Attribute
|
Description
|
Required
|
dir
|
The root of the directory tree of this FileSet.
|
Yes, Either dir or file must be specified
|
file
|
shortcut for specifying a single-file fileset
|
|
defaultexcludes
|
Indicates
whether default
excludes should be used or not (
yes | no );
default excludes are used when omitted. |
NO
|
includes
|
Comma-
or space-separated list of patterns of files that must be included; all files
are included when omitted.
|
NO
|
includesfile
|
The
name of a file; each line of this file is taken to be an include pattern.
|
NO
|
excludes
|
Comma-
or space-separated list of patterns of files that must be excluded; no files
(except default excludes) are excluded when omitted.
|
NO
|
excludesfile
|
The
name of a file; each line of this file is taken to be an exclude pattern.
|
NO
|
casesensitive
|
Must the include and exclude patterns be treated
in a case sensitive way? Defaults to true.
|
NO
|
followsymlinks
|
Shall symbolic links be followed? Defaults to
true. See the note below.
|
NO
|
erroronmissingdir
|
Specify what happens if the base directory does
not exist. If true a build error will happen, if false, the fileset will be
ignored/empty. Defaults to true. Since Ant 1.7.1 (default is
true for backward compatibility reasons.)
|
NO
|
Before going to depth about fileset I want to
discuss about structure of fileset elements –
Or:
Since both of these FileSets contain no patterns,
they match the default; every file in the base directory and all its
subdirectories, recursively.
Some Basic Use of fileset –
If one desires to delete any of these default
excluded files, for example, to delete all scratch files that editplus (a text
editor) made, recursively, one has to set defaultexcludes="no" so
that the defaults are not excluded and then one could use something like:
Includes all files ending in the extensions "java"
and "j2ee" in the base directory and all subdirectories, the pattern
is applied recursively in the subdirectories.
Includes all files those contain the string "java"
in the base directory and all sub directories, recursively. Excludes any
files in any directory called "j2ee", whether it occurs in the
current directory or any of the sub directories, recursively. Notice that the
syntax is slightly different, in that, include and name are used
instead of includes and exclude and name are used instead
of excludes. In the context of the sentences above, the word "recursively"
means that the pattern is applied to each of the subdirectories as well
as the base directory hence it is then applied to the sub-directories of the
sub-directories and so on. The pattern is applied to all directories under the
base directory.
A Bit about PatternSet
Patterns can be grouped to sets and later be referenced by theirid
attribute. They are defined via a patternset
element, which can appear
nested into a FileSet or a directory-based task that constitutes an implicit
FileSet. In addition, patternset
s
can be defined as a standalone element at the same level as target
— i.e., as children of project
as well as children of target
. Patternsets may be nested within
one another, adding the nested patterns to the parent patternset. A nested
patternset can be inverted using the
element (Since
Ant 1.7.1). Patterns can be specified by nested
, or
elements for example – Patterns can be specified by nested
,
or
elements
or the following attributes.Attribute | Discription |
include | Each such element defines a single pattern for files to include or exclude. |
includes | Comma- or space-separated list of patterns of files that must be included. All files are included when omitted. |
exclude | Each such element defines a single pattern for files to include or exclude. |
excludes | Comma- or space-separated list of patterns of files that must be excluded; no files (except default excludes) are excluded when omitted. |
includesfile | The name of a file; each line of this file is taken to be an include pattern. You can specify more than one include file by using a nested includesfile elements. |
excludesfile | The name of a file; each line of this file is taken to be an exclude pattern. You can specify more than one exclude file by using a nested excludesfile elements. |
Include and exclude
Include and exclude have three attributes among them name is required attribute. Two more attribute for conditional purpose these are if and unless. Following table say about this –
Attribute
|
Description
|
Required
|
name | The pattern to in/exclude. | YES |
if | Only use this pattern if the named property is set. | NO |
unless | Only use this pattern if the named property is not set | NO |
Includesfile and excludesfile
if you want to list the files to include or exclude external to your build file, you should use the includesfile/excludesfile attributes or elements. Using the attribute, you can only specify a single file of each type, while the nested elements can be specified more than once - the nested elements also support if/unless attributes you can use to test the existance of a property.
Attribute
|
Description
|
Required
|
name | The name of the file holding the patterns to in/exclude. | YES |
if | Only read this file if the named property is set | NO |
unless | Only read this file if the named property is not set | NO |
Ant Flow of Control
Since Ant does not contain any real control
structures like if..then..else, one has to manipulate Ant's ability to
call internal targets that support conditional execution to emulate the desired
control structures. In ant we can do such flow using customize task. For
example just look following build.xml –
Case – 2 Assuming the case where the first file, fileone, is present, and the second
file, filetwo
is not. The initial
condition will be set because fileone is
available so the call to then will be successful. The body of then contains
another condition which checks for the existence of the file filetwo, if it is available, the
property, inner-condition is set. Since the assumption is that filetwo is not available, the property inner-condition
will not be set. Calls to the targets inner.then and inner.else follow.
The execution of inner.then is conditional, dictated by (if="inner-condition")
so the body of inner.then will not be executed. The execution of inner
else is conditional, dictated by (unless="inner-condition")
so the body of inner.else will be executed since the only thing that
would stop the execution of it would be if inner-condition was set.
Case – 3 Assuming the case where
the first file, fileone,
and the second file, filetwo are
both available. The outer condition will cause the property condition to
be set because fileone is
available, so when the target then is called, the body will be executed.
The condition within then will cause the property inner-condition to
be set because filetwo is
available. This means that the call to inner.then will be successful.
Upon exiting inner.then, inner.else will be called but the body
will not be executed because innercondition is set. Upon exiting then,
else will be called but the body will not be executed because condition
is set.
ANT
USING EXTERNAL LIBRARIES (log4j)
In my previous example I ran a build file and output was
coming on console. But assume in case where output is required on log file or
other file. I mean I want to execute a build file using external file instead
of java IO API. So in this example I am going to use log4j API to write
information in log file instead of standard console.
We store the external
jar or library inside lib folder what we have created earlier. Here we are
putting the log4j jar inside lib folder. 2nd step would be to change
the HelloWorld.java code, and now HelloWorld.java looks like –
package com.greensoft.ant.example;
import org.apache.log4j.Logger;
import org.apache.log4j.BasicConfigurator;
/**
* @author Pravind
Kumar
*
*/
public class HelloWorld {
private
static Logger logger = Logger.getLogger(HelloWorld.class);
/**
* Default Constructor
*/
public
HelloWorld() {
}
/**
* @param args
*/
public
static void main(String[] args) {
//System.out.println("Hello
World By Pravind Kumar");
BasicConfigurator.configure();
logger.info("Hello
World By Pravind using Log4j api");
}
}
Now, it’s time to update
the build.xml file accordingly so that it can find the all imported class files
in class path otherwise it will show a couple of exception during compilation. In build.xml file add one more line for
property inside init target like this –
After that, to compile new java file need log4j jar file.
There are two ways to get log4j jar; one is to set that jar file into class
path of system environment variable and another is to set path element inside
build.xml file. So I think second option is better. To set the jar file in
build.xml, add following line of code into init target. Path element line looks
like this –
Path element is using to make a group of jar file
recursively using fileset element. About fileset element see the
above block.
above block.
We had coded BasicConfigurator.configure();
which implies a simple, but hard coded configuration. More confortable would be
using a property file. In the java source delete the BasicConfiguration-line
from the main() method (and the related import-statement). Log4J will search
then for a configuration as described in it's manual. Then create a new file src/log4j.properties. That's
the default name for Log4J's configuration and using that name would make life
easier - not only the framework knows what is inside, we too! So put this
properties file inside src (source ) directory. Properties file is –
log4j.properties
log4j.rootLogger=DEBUG, stdout
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%m%n
Now according to this configuration file we need to change
the compile target inside build.xml file. Thus new compile target look like
this –
Also update run target after updating run target looks like
–
And this is the final build.xml file and ready for execution
–
Just go on command prompt and switch to your application
folder and type “ant” and press enter. What’s up! Congratulation your
application is configured properly and in running state.
No comments:
Post a Comment