|
What
is ant?
|
Ant is a small animal who can
build magnificent buildings. Ant builds!
ANT is a Java based building tool, which is similar to make, and so
much better than make.
ANT, what a smart name for a building tool, even the original author of
ANT, James Duncan Davidson, meant "Another Neat Tool".
|
A
win-win ant learning method
|
There is a shortcut.
If you download a small jakarta project, such as Log4J, which is built
by ant. It is a good and simple example for you to learn ant. Actually,
you hit two birds with one stone.
Ant is easy!
The hard part is how to make a very complicated diversified system work
very simple and elegant. Knowledge about ant is not enough, you need an
elegant and simple design, you need great naming convention, you need
to optimize the code reusability and flexibility, you need a least
maintenance system...
Then it is not easy now ..
|
How
do I get started to use ant? Can you give me a "Hello World" ant script?
|
Simple.
* Download the most recent version of ant from
Apache; unzip it some where on your machine.
* Install j2sdk 1.4 or above.
* Set JAVA_HOME and ANT_HOME to the directory your
installed them respectively.
* Put %JAVA_HOME%/bin;%ANT_HOME%/bin on your Path.
Use ${JAVA_HOME}/bin:${ANT_HOME}/bin on UNIX. Yes, you can use forward
slash on windows.
* Write a "Hello world" build.xml
<project name="hello" default="say.hello" basedir="." >
<property name="hello.msg" value="Hello, World!" />
<target name="say.hello" >
<echo>${hello.msg}</echo>
</target>
</project>
* Type ant in the directory your build.xml located.
* You are ready to go!!!!
|
How
to delete files from a directory if it exists? The following code fails
when directory does not exist!
<delete quiet="true" dir="${classes.dir}" includes="*.class"/>
|
Your code has many problems.
1. You should not use implicit fileset, which is
deprecated. You should use nested fileset.
2. If dir does not exist, the build will fail, period!
3. If you are not sure, use a upper level dir, which
exists for sure. See the following fileset.
<delete>
<fileset dir="${upperdir.which.exists}">
<include
name="${classes.dir}/*.class" />
</fileset>
</delete>
|
How
do I set classpath in ant?
|
Here is some snippet of code
<path id="build.classpath">
<fileset dir="${build.lib}"
includes="**/*.jar"/>
<fileset dir="${build.classes}" />
</path>
<target....>
<javac ....>
<classpath refid="build.classpath"
/>
</java>
</target>
<target....>
<java ....>
<classpath refid="build.classpath"
/>
</java>
</target>
|
How
does ant read properties? How to set my property system?
|
Ant sets properties by order,
when something is set, the later same properties cannot overwrite the
previous ones. This is opposite to your Java setters.
This give us a good leverage of preset all properties in one place, and
overwrite only the needed. Give you an example here. You need password
for a task, but don't want to share it with your team members, or not
the developers outside your team.
Store your password in your ${user.home}/prj.properties
pswd=yourrealpassword
In your include directory master prj.properties
pswd=password
In your build-common.xml read properties files in this order
1. The commandline will prevail, if you use it: ant
-Dpswd=newpassword
2. ${user.home}/prj.properties (personal)
3. yourprojectdir/prj.properties (project team wise)
4. your_master_include_directory/prj.properties
(universal)
<cvsnttask password="${pswd} ... />
Problem solved!
|
How
to modify properties in ant?
|
No, you can't!
Properties in Ant are immutable. There is a good reason behind this,
see this FAQ item for more details.
Q. How to use ant-contrib tasks?
A: Simple, just copy ant-contrib.jar to your ant*/lib directory
And add this line into your ant script, all ant-contrib tasks are now
available to you!
<taskdef
resource="net/sf/antcontrib/antcontrib.properties" />
|
How
to loop on a list or fileset?
|
Use ant-contrib <for>
<foreach> tasks
General to say, use <for> is better than use <foreach>
since for each is actually open another ant property space, use more
memory too.
|
Why
do I get en exception when I use location="D:\\Code\\include" as
attribute of includepath?
|
See here.
You need to escape the string to "D:\\\\Code\\\\include" or use
"D:/Code/include" instead!
Believe me or not? Forward slash works on windows in all ant or java
code. It also works in windows environment variables. It does not work
in cmd (dos) window before XP. It also works in XP dos window now!
|
Can
I put the contents of a classpath or fileset into a property?
|
Yes, you can.
This is very similar to the call of Java class toString() method and
actually it is calling the toString() method inside ant. For example
<fileset id="fs1" dir="t1" includes="**/*.java"/>
<property name="f1.contents" refid="fs1"/>
<echo>f1.contents=${f1.contents}</echo>
|
Where
can I find the javadoc for ant API?
|
Download apache ant src version.
Use ant javadocs command to see generated javadoc for ant in build/docs
directory.
|

|
How
can I use ant to run a Java application?
|
Here is a real world example.
<target name="run" depends="some.target,some.other.target">
<java classname="${run.class}" fork="yes">
<classpath>
<path refid="classpath"
/>
</classpath>
<jvmarg line="${debug.jvmargs}" />
<jvmarg line="${my.jvmargs}" />
<jvmarg value="-Dname=${name}" />
<jvmarg line="${run.jvmargs}" />
<arg line="${run.args}" />
</java>
</target>
|
How
to use ant to run commandline command? How to get perl script running
result?
|
Use exec ant task.
Don't forget ant is pure Java. That is why ant is so useful, powerful
and versatile. If you want ant receive unix command and result, you
must think Unix. So does in MS-Windows. Ant just helps you to automate
the process.
|
How
do I debug my ant script?
|
Many ways
* Do an echo on where you have doubt. You will find
out what is the problem easily. Just like the old c printf() or Java
System.println()
* Use project.log("msg") in your javascript or
custom ant task
* Run Ant with -verbose, or even -debug, to get more
information on what it is doing, and where. However, you might be tired
with that pretty soon, since it give you too much information.
|
How
to exclude multi directories in copy or delete task?
|
Here is an example.
<copy todir="${to.dir}" >
<fileset dir="${from.dir}" >
<exclude name="dirname1" />
<exclude name="dirname2" />
<exclude name="abc/whatever/dirname3"
/>
<exclude name="**/dirname4" />
</fileset>
</copy>
|
How
to use Runtime in ant?
|
You don't need to use Runtime
etc. Ant have exec task.
The class name is org.apache.tools.ant.taskdefs.ExecTask. You can
create the task by using the code in your customized ant Task.
ExecTask compile = (ExecTask)project.createTask("exec");
|
How
to rearrange my directory structure in my jar/war/ear/zip file? Do I
need to unarchive them first?
|
No, you don't need to unarchive
them first.
* You don't need to unzip the files from archive to
put into your destination jar/ear/war files.
* You can use zipfileset in your jar/war/ear task to
extract files from old archive to different directory in your new
archive.
* You also can use zipfileset in your jar/war/ear
task to send files from local directory to different directory in your
new archive.
See the follow example:
<jar destfile="${dest}/my.jar">
<zipfileset src="old_archive.zip"
includes="**/*.properties" prefix="dir_in_new_archive/prop"/>
<zipfileset dir="curr_dir/abc"
prefix="new_dir_in_archive/xyz"/>
</jar>
|
Why
did I get such warning in ant?
compile:
[javac] Warning: commons-logging.properties modified in the future.
[javac] Warning: dao\\DAO.java modified in the future.
[javac] Warning: dao\\DBDao2.java modified in the future.
[javac] Warning: dao\\HibernateBase.java modified in the future.
|
System time problem, possible
reasons:
* You changed the system time
* I had the same problem before, I checked out files
from cvs to windows, and transfer them to a unix machine, somehow, I
got huge amount of such warnings because the system timing issue.
* If you transfer files from Australia/China/India
to the United States, you will get the problem too. True enough, I did
and met the problem once.
|
How
can I write my own ant task?
|
Easy!
Writing Your Own Task How-To from ant.
In your own $ANT_HOME/docs/manual directory, there also is
tutorial-writing-tasks-src.zip
Use them! Use taskdef to define it in your script, define it before
using it.
|
How
to copy files without extention?
|
If files are in the directory:
<include name="a,b,c"/>
If files are in the directory or subdirectories:
<include name="**/a,**/b,**/c"/>
If you want all files without extension are in the directory or
subdirectories:
<exclude name="**/*.*"/>
|
How
do I use two different versions of jdk in ant script?
|
The followings are what I'm
doing.
1. Don't define java.home by yourself. Ant uses an
internal one derived from your environment var JAVA_HOME. It is
immutable.
2. I do the followings:
* In my
build.properties (read first)
jdk13.bin=${tools.home}/jdk1.3.1_13/bin
jdk14.bin=${tools.home}/j2sdk1.4.2_08/bin/
* In my master
properties file (read last), set default
javac.location=${jdk13.bin}
* In my
prj.properties, if I need to use 1.4
javac.location=${jdk14.bin}
* in my javac
task
executable="${javac.location}/javac.exe"
|
How
to pass -Xlint or -Xlint:unchecked to 1.5 javac task?
|
pass it as compilerarg nested
<compilerarg> to specify.
<compilerarg value="-Xlint"/>
<!-- or -->
<compilerarg value="-Xlint:unchecked"/>
|
Can
you give me a simple ant xslt task example?
|
Here is a working one!
<xslt style="${xslfile}" in="${infile}"
out="${outfile}" >
<classpath>
<fileset
dir="${xml.home}/bin"
includes="*.jar"
/>
</classpath>
</xslt>
|
How
to hide password input?
|
Override ant Input task.
Response every user input with a backspace. Not the best, but it works
|
How
do I add elements to an existing path dynamically?
|
Yes, it is possible. However,
you need to write a custom ant task, get the path, and add/modify it,
and put it in use. What I am doing is that I define a path reference
lib.classpath, then add/modify the lib.classpath use my own task.
|
How
to do conditional statement in ant?
|
There are many ways to solve the
problem.
* Since target if/unless all depend on some property
is defined or not, you can use condition to define different NEW
properties, which in turn depends on your ant property values. This
makes your ant script very flexible, but a little hard to read.
* Ant-contrib has <if> <switch> tasks
for you to use.
* Ant-contrib also has <propertyregex> which
can make very complicate decisions.
|
Can
I change/override ant properties when I use ant-contrib foreach task?
|
<foreach> is actually
using a different property space, you can pass any property name/value
pair to it. Just use <param> nested tag inside foreach
|
How
to let auto-detect platform and use platform specific properties?
|
Tell you a great trick, it works
excellent.
In your major build-include.xml, put in this line
<property
file="${antutil.includes}/${os.name}-${os.arch}.properties" />
This will auto-detect your platform, and you write one file for each
environment specific variables. For example:
HP-UX-PA_RISC2.0.properties SunOS-sparc.properties Windows
XP-x86.properties ... They work great!!!
|
How
to make ant user interactive? I tried to use BufferedReader to get user
input, it hangs.
|
See here.
Use this class TimedBufferedReader instead of your BufferedReader will
work. This is a working one in our installation process. The original
author is credited in the code. I've made some improvement.
TimedBufferedReader.java
package setup;
import java.io.Reader;
import java.io.BufferedReader;
import java.io.IOException;
/**
* Provides a BufferedReader with a readLine method that
* blocks for only a specified number of seconds. If no
* input is read in that time, a specified default
* string is returned. Otherwise, the input read is returned.
* Thanks to Stefan Reich
* for suggesting this implementation.
* @author: Anthony J. Young-Garner
* @author: Roseanne Zhang made improvement.
*/
public class TimedBufferedReader extends BufferedReader
{
private int timeout = 60; //
1 minute
private String defaultStr = "";
/**
* TimedBufferedReader constructor.
* @param in Reader
*/
TimedBufferedReader(Reader in)
{
super(in);
}
/**
* TimedBufferedReader constructor.
* @param in Reader
* @param sz int Size of the input buffer.
*/
TimedBufferedReader(Reader in, int sz)
{
super(in, sz);
}
/**
* Sets number of seconds to block for input.
* @param seconds int
*/
public void setTimeout(int timeout)
{
this.timeout=timeout;
}
/**
* Sets defaultStr to use if no input is read.
* @param str String
*/
public void setDefaultStr(String str)
{
defaultStr = str;
}
/**
* We use ms internally
* @return String
*/
public String readLine() throws IOException
{
int waitms = timeout*1000;
int ms = 0;
while (!this.ready())
{
try
{
Thread.currentThread().sleep(10);
ms += 10;
}
catch (InterruptedException e)
{
break;
}
if (ms >= waitms)
{
return defaultStr;
}
}
return super.readLine();
}
}
|
What
is a good directory structure for main code and junit test code?
|
Dev
|_src
| |_com
| |_mycom
| |_mypkg
| |_A.java
|_test
|_src
|_com
|_mycom
|_mypkg
|_ATest.java
|
|

|
|