|
|
@@ -0,0 +1,793 @@ |
|
|
|
<head> |
|
|
|
<title> |
|
|
|
Ant in Anger |
|
|
|
</title> |
|
|
|
</head> |
|
|
|
|
|
|
|
<body bgcolor="#FFFFFF" text="#000000"> |
|
|
|
<h1 align="center">Ant in Anger: |
|
|
|
</h1> |
|
|
|
<h2 align="center"> |
|
|
|
Using Ant in a Production Development System |
|
|
|
</h2> |
|
|
|
|
|
|
|
<h4 align="center"> |
|
|
|
Steve Loughran (<a href="mailto:steve_l@iseran.com">steve_l@iseran.com</a>) |
|
|
|
</h4> |
|
|
|
|
|
|
|
<a name="introduction"> |
|
|
|
|
|
|
|
<h2>Introduction</h2> |
|
|
|
</a> |
|
|
|
|
|
|
|
<a href="http://jakarta.apache.org/ant/">Ant</a> |
|
|
|
can be an invaluable tool in a team development process -or it can |
|
|
|
be yet another source of problems in that ongoing crises we call |
|
|
|
development . This |
|
|
|
document contains some strategies and tactics for making the most of |
|
|
|
ant. It is moderately frivolous in places, and lacks almost any actual |
|
|
|
examples of ant xml. The lack of examples is entirely deliberate -it |
|
|
|
keeps document maintenance costs down. Most of the concepts covered |
|
|
|
don't need the detail about XML representations, as it is processes we |
|
|
|
are concerned about, not syntax. Finally, please be aware that the |
|
|
|
comments here are only suggestions which need to be customised to meet |
|
|
|
your own needs, not strict rules about what should and should not be |
|
|
|
done. |
|
|
|
|
|
|
|
<p> |
|
|
|
Firstly, here are some assumptions about the projects which this |
|
|
|
document covers |
|
|
|
<ul> |
|
|
|
<li> Pretty much pure Java. |
|
|
|
|
|
|
|
<li> Team efforts, usually with the petulant prima-donnas all us Java |
|
|
|
programmers become once we realise how much in demand we are. |
|
|
|
|
|
|
|
<li> A fairly distributed development team -spread across locations and |
|
|
|
maybe time zones. |
|
|
|
|
|
|
|
<li> Separate sub projects -from separate beans in a big |
|
|
|
enterprise application to separate enterprise applications which need to |
|
|
|
be vaguely aware of each other. |
|
|
|
|
|
|
|
<li> Significant mismatch between expectations and time available to |
|
|
|
deliver. 'Last Week' is the ideal delivery date handed down from above, |
|
|
|
next century the date coming up from below. |
|
|
|
|
|
|
|
<li> Everyone is struggling to keep up with platform and tool evolution. |
|
|
|
|
|
|
|
<li> Extensive use of external libraries, both open and closed source. |
|
|
|
|
|
|
|
</ul> |
|
|
|
|
|
|
|
What that all means is that there is no time to spend getting things |
|
|
|
right, you don't have that tight control on how the rest of the team |
|
|
|
works and the development process is often more one of chaos minimisation |
|
|
|
than anything else. The role of ant in such projects is to ensure that |
|
|
|
the build, test and deploy processes run smoothly, leaving you with all |
|
|
|
the other problems. |
|
|
|
|
|
|
|
<a name="core"> |
|
|
|
<h2>Core Practices</h2> |
|
|
|
</a> |
|
|
|
<h3> |
|
|
|
Clarify what you want ant to do</h3> |
|
|
|
|
|
|
|
|
|
|
|
Ant is not a silver bullet. It is just another rusty bullet in the armory of |
|
|
|
development tools available at your disposal. Its primary purpose is to |
|
|
|
accelerate the construction and deployment of Java projects. You could certainly |
|
|
|
extend ant to do anything Java makes possible -it is easy to imagine writing an |
|
|
|
image processing task to help in web site deployment by shrinking and |
|
|
|
recompressing jpeg files, for example. But that would be pushing the boundary of |
|
|
|
what ant is really intended to do -so should be considered with care. |
|
|
|
|
|
|
|
<P> |
|
|
|
|
|
|
|
Ant is also a great adjunct to an IDE -a way of doing all the housekeeping of |
|
|
|
deployment and for clean, automated builds. But a good modern IDE is a |
|
|
|
productivity tool in its own right -one you should consider keeping using. Ant |
|
|
|
just lets you give the teams somewhat more freedom in IDE choice -"you can |
|
|
|
use whatever you want in development, but ant for the deployment |
|
|
|
builds" |
|
|
|
|
|
|
|
<h3> |
|
|
|
Define standard targets |
|
|
|
</h3> |
|
|
|
|
|
|
|
|
|
|
|
When you have multiple sub projects, define a standard set of targets. |
|
|
|
Projects with a split between interface and implementation jar files |
|
|
|
could consider <b>impl</b> and <b>intf</b> targets -with separate |
|
|
|
<b>debug-impl</b>and <b>debug-intf</b> targets for the debug version. |
|
|
|
And of course, the ubiquitous <b>clean</b> target. |
|
|
|
|
|
|
|
<P> |
|
|
|
|
|
|
|
With standard target names, it is easy to build encompassing ant build |
|
|
|
files which just hand off the work to the classes below using the |
|
|
|
<a href="index.html#ant">ant</a> |
|
|
|
task. For example. the clean target could be handed down to the intf and |
|
|
|
impl subdirectories from a parent directory |
|
|
|
|
|
|
|
<pre><target name="clean" depends="clean-intf, clean-impl"> |
|
|
|
</target> |
|
|
|
|
|
|
|
<target name="clean-intf" > |
|
|
|
<ant dir="intf" target="clean" /> |
|
|
|
</target> |
|
|
|
|
|
|
|
<target name="clean-impl"> |
|
|
|
<ant dir="impl" target="clean" /> |
|
|
|
</target> </pre> |
|
|
|
|
|
|
|
<h3> |
|
|
|
Extend ant through new tasks |
|
|
|
</h3> |
|
|
|
|
|
|
|
If ant does not do what you want, you can use the |
|
|
|
<a href="index.html#exec">exec</a> and |
|
|
|
<a href="index.html#java">java</a> tasks or |
|
|
|
<a href="index.html#script">inline scripting</a> to extend it. In a |
|
|
|
project with many build.xml files, you soon find that having a single |
|
|
|
central place for implementing the functionality keeps maintenance |
|
|
|
overhead down. Implementing task extensions through java code seems |
|
|
|
extra effort at first, but gives extra benefits:- |
|
|
|
|
|
|
|
<ul> |
|
|
|
|
|
|
|
<li>Cross platform support can be added later without changing any |
|
|
|
build.xml files</li> |
|
|
|
|
|
|
|
<li>The code can be submitted to the ant project itself, for other |
|
|
|
people to use and maintain</li> |
|
|
|
|
|
|
|
<li>It keeps the build files simpler</li> |
|
|
|
|
|
|
|
</ul> |
|
|
|
|
|
|
|
<h3> |
|
|
|
Embrace Automated Testing |
|
|
|
</h3> |
|
|
|
|
|
|
|
<b>(alternatively "recriminate early, recriminate often")</b> |
|
|
|
<p> |
|
|
|
|
|
|
|
Ant lets you call <a href="junit.html">JUnit</a> tasks, which unit test |
|
|
|
the code your team has written. Automated testing may seem like extra |
|
|
|
work at first, but JUnit makes writing unit tests so easy that you have |
|
|
|
almost no reason not to. Invest the time in learning how to use |
|
|
|
JUnit, write the test cases, and integrate them in a 'test' target from |
|
|
|
ant so that your daily or hourly team build can have the tests applied |
|
|
|
automatically. |
|
|
|
|
|
|
|
<p> |
|
|
|
|
|
|
|
Once code fetches from the code control system are added as another ant |
|
|
|
target, the integration test code can be a pure ant task run on any box |
|
|
|
dedicated to the task. This is ideal for verifying that the build and |
|
|
|
unit tests work on different targets from the usual development |
|
|
|
machines. For example, a Win95/Java1.1 combination could be used even |
|
|
|
though no developer would willingly use that configuration given the |
|
|
|
choice. |
|
|
|
|
|
|
|
<p> |
|
|
|
|
|
|
|
System tests are harder to automate than unit tests, but if you can |
|
|
|
write java code to stress large portions of the system -even if the code |
|
|
|
can not run as JUnit tasks- then the <a href= "index.html#java">java</a> |
|
|
|
task can be used to invoke them. It is best to specify that you want a |
|
|
|
new JVM for these tests, so that a significant crash does not break the |
|
|
|
full build. |
|
|
|
|
|
|
|
|
|
|
|
<a name="crossplatform"> |
|
|
|
<h2> |
|
|
|
Cross Platform Ant |
|
|
|
</h2> |
|
|
|
</a> |
|
|
|
|
|
|
|
Ant is the best foundation for cross platform Java development and |
|
|
|
testing to date. But if you are not paying attention, it is possible to |
|
|
|
produce build files which only work on one platform -or indeed, one |
|
|
|
single workstation. |
|
|
|
|
|
|
|
<p> |
|
|
|
|
|
|
|
The common barriers to cross-platform ant are the use of command line |
|
|
|
tools (exec tasks) which are not portable, path issues, and hard coding |
|
|
|
in the location of things. |
|
|
|
|
|
|
|
<h3>Command Line apps: <a href="index.html#exec">Exec</a>/ <a href= |
|
|
|
"index.html#execon">ExecOn</a></h3> |
|
|
|
|
|
|
|
The trouble with external invocation is that not all functions are found |
|
|
|
cross platform, and those that are often have different names -DOS |
|
|
|
descendants often expect .exe or .bat at the end of files. That can be |
|
|
|
bad if you explicitly include the extension in the naming of the command |
|
|
|
(don't!), good when it lets you keep the unix and DOS versions of an |
|
|
|
executable in the same bin directory of the project without name |
|
|
|
clashes arising. |
|
|
|
|
|
|
|
<p> |
|
|
|
|
|
|
|
Both the command line invocation tasks let you specify which platform |
|
|
|
you want the code to run on, so you could write different tasks for each |
|
|
|
platform you are targeting. Alternatively, the platform differences |
|
|
|
could be handled inside some external code which ant calls. This can be |
|
|
|
some compiled down java in a new task, or an external script file. |
|
|
|
|
|
|
|
<h3>Cross platform paths</h3> |
|
|
|
|
|
|
|
Unix paths use forward slashes between directories and a colon to |
|
|
|
split entries. Thus |
|
|
|
<i>"/bin/java/lib/xerces.jar:/bin/java/lib/ant.jar"</i> is |
|
|
|
a path in unix. In Windows the path must use semicolon separators, |
|
|
|
colons being used to specify disk drives, and backslash separators |
|
|
|
<i>"c:\bin\java\lib\xerces.jar;c:\bin\java\lib\ant.jar"</i>. |
|
|
|
|
|
|
|
This difference between platforms (indeed, the whole java classpath |
|
|
|
paradigm) can cause hours of fun. |
|
|
|
|
|
|
|
<p> |
|
|
|
|
|
|
|
Ant reduces path problems; but does not eliminate them entirely. You |
|
|
|
need to put in some effort too. The rules for handling path names are |
|
|
|
that 'DOS-like pathnames are handled', 'Unix like paths are handled'. |
|
|
|
Disk drives -'C:'- are handled on DOS-based boxes, but placing them in |
|
|
|
the build.xml file ruins all chances of portability. Relative file paths |
|
|
|
are much more portable. Semicolons work as path separators -a fact which |
|
|
|
is useful if your ant invocation wrapper includes a list of jars as a |
|
|
|
defined property in the command line. In the build files you may find it |
|
|
|
better to build a classpath by listing individual files (using location= |
|
|
|
attributes), or by including a fileset of *.jar in the classpath |
|
|
|
definition. |
|
|
|
|
|
|
|
|
|
|
|
<p> |
|
|
|
Note that DOS descended file systems are case insensitive (apart from |
|
|
|
the obscure aberration of the WinNT posix subsystem run against NTFS), |
|
|
|
and that Windows pretends that all file extensions with four or more |
|
|
|
letters are also three letter extensions (try DELETE *.jav in your java |
|
|
|
directories to see a disastrous example of this). |
|
|
|
|
|
|
|
<p> |
|
|
|
|
|
|
|
Ant's policy on case sensitivity is whatever the underlying file system |
|
|
|
implements *VERIFY*, and its handling of file extensions is that *.jav does not |
|
|
|
find any .java files. The Java compiler is of course case sensitive -you can |
|
|
|
not have a class 'ExampleThree' implemented in "examplethree.java". |
|
|
|
|
|
|
|
<p> |
|
|
|
|
|
|
|
Some tasks only work on one platform -<a href= "index.html#chmod"> |
|
|
|
Chmod</a> being a classic example. These tasks usually result in just a |
|
|
|
warning message on an unsupported platform -the rest of the target's |
|
|
|
tasks will still be called. Other tasks degrade their functionality on |
|
|
|
platforms or Java versions. In particular, any task which adjusts the |
|
|
|
timestamp of files can not do so properly on Java 1.1. Tasks which can |
|
|
|
do that - <a href="index.html#get">Get<a>, <a |
|
|
|
href="index.html#touch">Touch</a> and <A href="index.html#unzip"> |
|
|
|
Unjar/Unwar/Unzip</a> for example, degrade their functionality on |
|
|
|
Java1.1, usually resorting to the current timestamp instead. |
|
|
|
|
|
|
|
|
|
|
|
<p> |
|
|
|
|
|
|
|
Finally, Perl makes a good place to wrap up Java invocations cross |
|
|
|
platform, rather than batch files. It is included in most Unix |
|
|
|
distributions, and is a simple download for <a href= |
|
|
|
"http://www.activestate.com/Products/ActivePerl/"> Win32 platforms from |
|
|
|
ActiveState</a>. A Perl file with .pl extension, with the usual Unix |
|
|
|
path to perl on the line 1 comment and marked as executable can be run |
|
|
|
on Windows, OS/2 and Unix and hence called from Ant without issues. The |
|
|
|
perl code can be left to resolve its own platform issues. |
|
|
|
|
|
|
|
<a name="team"> |
|
|
|
<h2>Team Development Processes</h2> |
|
|
|
</a> |
|
|
|
|
|
|
|
Even if each team member is allowed their choice of IDE/editor, or even |
|
|
|
OS, you need to set a baseline of functionality on each box. In |
|
|
|
particular, the JDKs and jars need to be in perfect sync. Ideally pick |
|
|
|
the latest stable Java/JDK version available on all developer/target |
|
|
|
systems and stick with it for a while. Consider assigning one person to |
|
|
|
be the contact point for all tools coming in -particularly open source |
|
|
|
tools when a new build is available on a nightly basis. Unless needed, |
|
|
|
these tools should only really be updated monthly, or when a formal |
|
|
|
release is made. |
|
|
|
|
|
|
|
<p> |
|
|
|
|
|
|
|
Another good tactic is to use a unified directory tree, and add on extra |
|
|
|
tools inside that tree. All references can be made relative to the tree. |
|
|
|
If team members are expected to add a directory in the project to their |
|
|
|
path, then command line tools can be included there -including those |
|
|
|
invoked by ant exec tasks. Put everything under source code control and |
|
|
|
you have a one stop shop for getting a build/execute environment purely |
|
|
|
from CVS or your equivalent. |
|
|
|
|
|
|
|
|
|
|
|
<a name="deploying"> |
|
|
|
<h2>Deploying with Ant</h2> |
|
|
|
</a> |
|
|
|
|
|
|
|
One big difference between ant and older tools such as make is that the |
|
|
|
processes for deploying java to remote sites are reasonably well |
|
|
|
evolved in ant. That is because we all have to do it these days, so |
|
|
|
many people have put in the effort to make the tasks easier. |
|
|
|
<p> |
|
|
|
|
|
|
|
Ant can <a href="index.html#jar">Jar</a>, <a href= "index.html#tar"> |
|
|
|
Tar</a> or <a href="index.html#zip">Zip</a> files for deployment, while |
|
|
|
the <a href="index.html#war">War</a> task extends the jar task for |
|
|
|
better servlet deployment. <a href = "jlink.html" >Jlink</a> is a jar |
|
|
|
generation file which lets you merge multiple sub jars. This is ideal |
|
|
|
for a build process in which separate jars are generated by sub |
|
|
|
projects, yet the final output is a merged jar. <a href= |
|
|
|
"index.html#cab">Cab</a> can be used on Win32 boxes to build a cab file |
|
|
|
which is useful if you have to target IE deployment. |
|
|
|
|
|
|
|
<p> |
|
|
|
|
|
|
|
The <a href = "index.html#ftp">ftp</a> task lets you move stuff up to a |
|
|
|
server. Beware of putting the ftp password in the build file -a property |
|
|
|
file with tight access control is slightly better. The <a href= |
|
|
|
"index.html#fixcrlf">FixCRLF task</a> is often a useful interim step if |
|
|
|
you need to ensure that files have unix file extensions before upload. A |
|
|
|
WebDav task has long been discussed, which would provide a more secure |
|
|
|
upload to web servers, but it is still in the todo list. If DAV is your |
|
|
|
required upload mechanism, why not take up the challenge? |
|
|
|
|
|
|
|
<p> |
|
|
|
|
|
|
|
EJB deployment is aided by the <a href="ejb.html">ejb tasks</a>. At the |
|
|
|
time of writing, only WebLogic was supported with these tasks -if your |
|
|
|
EJB server is not supported, extending the ejb tasks would benefit your |
|
|
|
project and the rest of the ant community. |
|
|
|
|
|
|
|
<p> |
|
|
|
|
|
|
|
Finally, there are of course the fallbacks of just copying files to a |
|
|
|
destination using <a href="index.html#copy">Copy</a> and <a href = |
|
|
|
"index.html#copydir">Copydir</a> , or just sending them to a person or |
|
|
|
process using <a href= "index.html#mail">Mail</a>. |
|
|
|
|
|
|
|
<a name="directories"> |
|
|
|
<h2> Directory Structures</h2> |
|
|
|
</a> |
|
|
|
|
|
|
|
How you structure your directory tree is very dependent upon the |
|
|
|
project. Here are some directory layout patterns which can be used as |
|
|
|
starting points. |
|
|
|
|
|
|
|
<h3>Simple Project</h3> |
|
|
|
|
|
|
|
The project contains sub directories |
|
|
|
<table width="100%"> |
|
|
|
<tr> |
|
|
|
<td><b>bin</b> |
|
|
|
</td> |
|
|
|
<td>common binaries, scripts -put this on the path. |
|
|
|
</td> |
|
|
|
</tr> |
|
|
|
|
|
|
|
<tr> |
|
|
|
<td><b>build</b> |
|
|
|
</td> |
|
|
|
<td>This is the tree for building; ant creates it and can empty it |
|
|
|
in the 'clean' project. |
|
|
|
</td> |
|
|
|
</tr> |
|
|
|
<tr> |
|
|
|
<td><b>dist</b> |
|
|
|
</td> |
|
|
|
<td>Distribution outputs go in here; the directory is created in ant |
|
|
|
and clean empties it out |
|
|
|
</td> |
|
|
|
</tr> |
|
|
|
<tr> |
|
|
|
<td><b>doc</b> |
|
|
|
</td> |
|
|
|
<td>Hand crafted documentation |
|
|
|
</td> |
|
|
|
</tr> |
|
|
|
<tr> |
|
|
|
<td><b>lib</b> |
|
|
|
</td> |
|
|
|
<td>Imported Java libraries go in to this directory |
|
|
|
</td> |
|
|
|
</tr> |
|
|
|
<tr> |
|
|
|
<td><b>src</b> |
|
|
|
</td> |
|
|
|
<td>source goes in under this tree |
|
|
|
</td> |
|
|
|
</tr> |
|
|
|
</table> |
|
|
|
|
|
|
|
The bin, lib, doc and src directories should be under source code control. |
|
|
|
Slight variations include an extra tree of content to be included in the |
|
|
|
distribution jars -inf files, images, etc. Javadoc output can be |
|
|
|
directed to a doc/ folder beneath build/, or to doc/javadoc. |
|
|
|
|
|
|
|
<h3>Interface and Implementation split</h3> |
|
|
|
|
|
|
|
If the interface is split from the implementation code then this can be |
|
|
|
supported with minor changes just by having a separate build path for |
|
|
|
the interface directory -or better still just in the jar construction: |
|
|
|
one jar for interface and one jar for implementation. |
|
|
|
|
|
|
|
|
|
|
|
<h3>Loosely Coupled Sub Projects</h3> |
|
|
|
|
|
|
|
In the loosely coupled approach multiple projects can have their own |
|
|
|
copy of the tree, with their own source code access rights. |
|
|
|
One difference to consider is only having one instance of the bin and |
|
|
|
lib directories across all projects. This is sometimes good -it helps |
|
|
|
keep copies of xerces.jar in sync, and sometimes bad -it can update |
|
|
|
foundational jar files before unit testing is complete. |
|
|
|
|
|
|
|
<p> |
|
|
|
|
|
|
|
To still have a single build across the sub projects, use parent |
|
|
|
build.xml files which call down into the sub projects. |
|
|
|
|
|
|
|
<p> |
|
|
|
|
|
|
|
This style works well if different teams have different code |
|
|
|
access/commitment rights. The risk is that by giving extra leeway to the |
|
|
|
sub projects, you can end up with incompatible source, libraries, build |
|
|
|
processes and just increase your workload and integration grief all round. |
|
|
|
|
|
|
|
<h3>Integrated sub projects</h3> |
|
|
|
|
|
|
|
Tightly coupled projects have all the source in the same tree; different |
|
|
|
projects own different subdirectories. Build files can be moved down to |
|
|
|
those subdirectores (say src/com/iseran/core and src/com/iseran/extras), |
|
|
|
or kept at the top -with independent build files named core.xml and |
|
|
|
extras.xml |
|
|
|
|
|
|
|
<p> |
|
|
|
|
|
|
|
This project style works well if everyone trusts each other and the |
|
|
|
sub projects are not too huge or complex. The risk is that a split to a |
|
|
|
more loosely coupled design will become a requirement as the projects |
|
|
|
progress -but by the time this is realised schedule pressure and |
|
|
|
intertwined build files make executing the split well nigh impossible. |
|
|
|
If that happens then just keep with it until there is the time to |
|
|
|
refactor the project directory structures. |
|
|
|
|
|
|
|
<a name="antupdate"> |
|
|
|
<h2> |
|
|
|
Ant Update Policies |
|
|
|
</h2> |
|
|
|
</a> |
|
|
|
|
|
|
|
Once you start using ant, you should have a policy on when and how the |
|
|
|
team updates their copies. A simple policy is "every official release |
|
|
|
after whatever high stress milestone has pushed all unimportant tasks |
|
|
|
(like sleep and seeing daylight) on the back burner". This insulates you |
|
|
|
from the changes and occasional instabilities that ant goes through |
|
|
|
during development. Its main disadvantage is that it isolates you from |
|
|
|
the new tasks and features that ant is constantly adding. |
|
|
|
|
|
|
|
<p> |
|
|
|
|
|
|
|
Often an update will require changes to the build.xml files. Most |
|
|
|
changes are intended to be backwards compatible, but sometimes an |
|
|
|
incompatible change turns out to be |
|
|
|
necessary. That is why doing the update in the lull after a big |
|
|
|
milestone is important. It is also why including ant.jar and related |
|
|
|
files in the CVS tree helps ensure that old versions of your software |
|
|
|
can be still be built. |
|
|
|
|
|
|
|
<p> |
|
|
|
|
|
|
|
The most aggressive strategy is to get a weekly or daily snapshot of the |
|
|
|
ant source, build it up and use it. This forces you to tweak the |
|
|
|
build.xml files more regulary, as new tasks and attributes can take |
|
|
|
while to stabilise. You really have to want the new features, enjoy |
|
|
|
gratuitous extra work or take pleasure in upsetting your colleagues to |
|
|
|
take this approach. |
|
|
|
|
|
|
|
<p> |
|
|
|
|
|
|
|
Once you start extending ant with new tasks, it suddenly becomes much |
|
|
|
more tempting to pull down regular builds. The most recent ant builds |
|
|
|
are invariably the the best platform for writing your extensions, as you |
|
|
|
can take advantage of the regular enhancements to the foundational |
|
|
|
classes. It also prevents you from wasting time working on something |
|
|
|
which has already been done. A newly submitted task to do something |
|
|
|
complex such as talk to EJB engines, SOAP servers or just convert a text |
|
|
|
file to uppercase may be almost exactly what you need -so take it, |
|
|
|
enhance it and offer up the enhancements to the rest of the world. This |
|
|
|
is certainly better than starting work on your 'text case converter' |
|
|
|
task on Ant 0.8 in isolation, announcing its existence six months latter |
|
|
|
and discovering that instead of adulation all you get are helpful |
|
|
|
pointers to the existing implementation. |
|
|
|
|
|
|
|
<p> |
|
|
|
|
|
|
|
You should also get on the <a href = |
|
|
|
"mailto:ant-dev-subscribe@jakarta.apache.org" > ant-dev mailing list |
|
|
|
</a>, as it is where the other developers post their work, problems and |
|
|
|
experience. The volume can be quite high: 40+ messages a day, so |
|
|
|
consider routing it to an email address you don't use for much else. And |
|
|
|
don't make everyone on the team subscribe; it can be too much of a |
|
|
|
distraction. |
|
|
|
|
|
|
|
|
|
|
|
<a name="tips"> |
|
|
|
<h2> |
|
|
|
Tips and Tricks</h2> |
|
|
|
</a> |
|
|
|
<dl> |
|
|
|
<dt><b> |
|
|
|
get |
|
|
|
</b><dd> |
|
|
|
|
|
|
|
The <a href="index.html#get">get</a> task can fetch any URL, so be used |
|
|
|
to trigger remote server side code during the build process, from remote |
|
|
|
server restarts to sending SMS/pager messages to the developer |
|
|
|
cellphones |
|
|
|
|
|
|
|
<dt><b> |
|
|
|
i18n |
|
|
|
</b><dd> |
|
|
|
|
|
|
|
|
|
|
|
Internationalisation is always trouble. Ant helps here with the <A href= |
|
|
|
"native2ascii.html">native2ascii</a> task which can escape out all non |
|
|
|
ascii characters into unicode. You can use this to write java files |
|
|
|
which include strings (and indeed comments) in your own non-ASCII |
|
|
|
language and then use native2ascii to convert to ascii prior to feeding |
|
|
|
through javac. The rest of i18n and l12n is left to you... |
|
|
|
|
|
|
|
<dt><b> |
|
|
|
Use Property Files |
|
|
|
</b><dd> |
|
|
|
|
|
|
|
Use external property files to keep per-user settings out the build |
|
|
|
files -especially passwords. Property files can also be used to |
|
|
|
dynamically set a number of properties based on the value of a single |
|
|
|
property, simply by dyamically generating the property filename from the |
|
|
|
source property. They can also be used as a source of constants across |
|
|
|
multiple build files. |
|
|
|
|
|
|
|
<dt><b> |
|
|
|
Faster compiles with Jikes |
|
|
|
</b><dd> |
|
|
|
|
|
|
|
The <a href="http://www.jikes.org/">jikes compiler</a> is usually much |
|
|
|
faster than javac, and does dependency checking. Get it. Then set |
|
|
|
build.compiler to "jikes" for it to be used in your build files. |
|
|
|
|
|
|
|
<dt><b> |
|
|
|
#include targets to simplify multi build.xml projects |
|
|
|
</b><dd> |
|
|
|
|
|
|
|
You can import XML files into a build file using <?import?> |
|
|
|
an element of XML syntax which the standard parsers use. This lets |
|
|
|
a multi-project development program share code through reference, |
|
|
|
rather than cut and paste re-use. It also lets one build up a file of |
|
|
|
standard tasks which can be reused over time. Because the import |
|
|
|
mechanism is at a level below which ant is aware, treat it as |
|
|
|
equivalent to the #include mechanism of the 'legacy' languages C and |
|
|
|
C++. |
|
|
|
|
|
|
|
<dt><b> |
|
|
|
Implement complex Ant builds through XSL |
|
|
|
</b><dd> |
|
|
|
|
|
|
|
XSLT can be used to dynamically generate build.xml files from a source |
|
|
|
xml file, with the <a href="index.html#style">Style</a> task controlling |
|
|
|
the transform. This is the current recommended strategy for creating |
|
|
|
complex build files dynamically. |
|
|
|
|
|
|
|
|
|
|
|
<dt><b> |
|
|
|
Change the invocation scripts |
|
|
|
</b><dd> |
|
|
|
|
|
|
|
By writing your own invocation script -using the DOS, Unix or Perl |
|
|
|
script as a starting point- you can modify a ant behavior for an |
|
|
|
individual project. For example, you can use an alternate variable to |
|
|
|
ANT_HOME as the base, extend the classpath differently, or dynamically |
|
|
|
create a new command line property 'project.interfaces' from all .jar |
|
|
|
files in an interfaces directory. |
|
|
|
|
|
|
|
<p> |
|
|
|
|
|
|
|
Having a custom invocation script which runs off a CVS controlled |
|
|
|
library tree under PROJECT_HOME also lets you control ant versions |
|
|
|
across the team -developers can have other copies of ant if they want, |
|
|
|
but the CVS tree always contains the jar set used to build your project. |
|
|
|
|
|
|
|
<p> |
|
|
|
|
|
|
|
You can also write wrapper scripts which invoke the existing ant |
|
|
|
scripts. This is an easy way to extend them. The wrapper scripts can add |
|
|
|
extra definitions and name explicit targets, redefine ANT_HOME and |
|
|
|
generally make development easier. Note that "ant" in Windows is really |
|
|
|
"ant.bat", so should be invoked from another batch file with a "CALL |
|
|
|
ant" statement -otherwise it never returns to your wrapper. |
|
|
|
|
|
|
|
|
|
|
|
<dt><b> |
|
|
|
Write all code so that it can be called from Ant |
|
|
|
</b><dd> |
|
|
|
|
|
|
|
This seems a bit strange and idealistic, but what it means is that you should |
|
|
|
write all your java code as if it may be called as a library at some point in |
|
|
|
future. So do not place calls to <b>System.exit()</b> deep in the code -if you |
|
|
|
want to exit a few functions in, raise an exception instead and have |
|
|
|
<b>main()</b> deal with it. |
|
|
|
|
|
|
|
<dt><b> |
|
|
|
Use Antidote as the invocation tool |
|
|
|
</b><dd> |
|
|
|
Even if you edit ant files by hand, Antidote makes a good execution tool |
|
|
|
because it eliminates the startup time of the JVM, perhaps even some of |
|
|
|
the XML parsing delays. |
|
|
|
|
|
|
|
</dl> |
|
|
|
|
|
|
|
<a name="puttingtogether"> |
|
|
|
<h2> |
|
|
|
Putting it all together |
|
|
|
</h2> |
|
|
|
</a> |
|
|
|
|
|
|
|
What does an ant build process look like in this world? Assuming a |
|
|
|
single directory structure for simplicity, the build file |
|
|
|
should contain a number of top level targets |
|
|
|
<ul> |
|
|
|
<li>build - do an (incremental) build |
|
|
|
<li>test - run the junit tests |
|
|
|
<li>clean - clean out the output directories |
|
|
|
<li>deploy - ship the jars, wars, whatever to the execution system |
|
|
|
<li>publish - output the source and binaries to any distribution site |
|
|
|
<li>fetch - get the latest source from the cvs tree |
|
|
|
<li>docs/javadocs - do the documenation |
|
|
|
<li>all - clean, fetch, build, test, docs, deploy |
|
|
|
<li>main - the default build process (usually build or build & test) |
|
|
|
</ul> |
|
|
|
Sub projects 'web', 'bean-1', 'bean-2' can be given their own build |
|
|
|
files -web.xml, bean-1.xml, bean-2.xml- with the same entry points. |
|
|
|
Extra toplevel tasks related to databases, web site images and the like |
|
|
|
should be considered if they are part of the process. |
|
|
|
|
|
|
|
<p> |
|
|
|
Debug/release switching can be handled with separate initialisation |
|
|
|
targets called before the compile tasks which define the appropriate |
|
|
|
properties. |
|
|
|
|
|
|
|
<p> |
|
|
|
Internal targets should be used to structure the process |
|
|
|
<ul> |
|
|
|
<li> init - initialise properties, extra-tasks, read in per-user |
|
|
|
property files. |
|
|
|
<li> init-debug - initialise debug properties |
|
|
|
<li> init-release - initialise release properties |
|
|
|
<li> compile - do the actual compilation |
|
|
|
<li> link/jar - make the jars or equivalent |
|
|
|
<li> staging - any pre-deployment process in which the output is dropped |
|
|
|
off then tested before being moved to the production site. |
|
|
|
</ul> |
|
|
|
|
|
|
|
The switching between debug and release can be done using the 'if' and |
|
|
|
'unless' conditional flags on the targets, so that debug gets called |
|
|
|
unless 'project.mode.release' is defined. |
|
|
|
|
|
|
|
<p> |
|
|
|
|
|
|
|
It is useful to define a project name property which can be echoed in |
|
|
|
the init task. This lets you work out which ant file is breaking in a |
|
|
|
multi file build. |
|
|
|
|
|
|
|
<p> |
|
|
|
|
|
|
|
What goes in to the internal ant tasks depends on your own projects. One |
|
|
|
very important tactic is 'keep path redefinition down through |
|
|
|
references' - you can reuse paths by giving them an ID and then |
|
|
|
referring to them via the 'refid' attribute you should only need to |
|
|
|
define a shared classpath once in the file; filesets can be reused |
|
|
|
similarly. |
|
|
|
|
|
|
|
<p> |
|
|
|
|
|
|
|
Once you have set up the directory structures, and defined the ant tasks |
|
|
|
it is time to start coding. An early priority must be to set up the |
|
|
|
automated test process, as that not only helps ensures that the code |
|
|
|
works, it verifies that the build process is working. |
|
|
|
|
|
|
|
<p> |
|
|
|
|
|
|
|
And that's it. The build file shouldn't need changing as new source |
|
|
|
files get added, only when you want to change the deliverables or part |
|
|
|
of the build process. At some point you may want to massively |
|
|
|
restructure the entire build process, restructuring projects and the |
|
|
|
like, but even then the build file you have should act as a foundation |
|
|
|
for a split build file process -just pull out the common properties into |
|
|
|
a properties file all build files read in, keep the target names unified |
|
|
|
and keep going with the project. Restructuring the source code control |
|
|
|
system is often much harder work. |
|
|
|
|
|
|
|
<h2>The Limits of Ant</h2> |
|
|
|
|
|
|
|
Before you start adopting ant as the sole mechanism for the build |
|
|
|
process, you need to be aware of what it doesn't do. |
|
|
|
<p> |
|
|
|
|
|
|
|
<h3>It's not a scripting language</h3> |
|
|
|
|
|
|
|
Ant lets you declare what you want done, with a bit of testing of the |
|
|
|
platform and class libraries first to enable some platform specific |
|
|
|
builds to take place. It does not let you specify how to handle things |
|
|
|
going wrong (a listener class can do that), or support complex |
|
|
|
conditional statements. |
|
|
|
|
|
|
|
<p> |
|
|
|
|
|
|
|
If your build needs to handle exceptions then look at the sound listener |
|
|
|
as a simple example of how to write your own listener class. Complex |
|
|
|
conditional statements can be handled by having something else do the |
|
|
|
tests and then build the appropriate ant task. XSLT can be used for |
|
|
|
this. |
|
|
|
|
|
|
|
<h3>It's not Make</h3> |
|
|
|
|
|
|
|
Some of the features of make, specifically inference rules and |
|
|
|
dependency checking are not included in ant. That's because they are |
|
|
|
'different' ways of doing a build. Make requires you to state |
|
|
|
dependencies and the build steps, ant wants you to state tasks and the |
|
|
|
order between them, the tasks themselves can do depedency checking or |
|
|
|
not. A full java build using Jikes is so fast that dependency checking |
|
|
|
is relatively moot, while many of the other tasks (but not all), compare |
|
|
|
the timestamp of the source file with that of the destination file |
|
|
|
before acting. |
|
|
|
|
|
|
|
<h3>It's not meant to be a nice language for humans</h3> |
|
|
|
|
|
|
|
XML isnt a nice representation of information for humans. It's a |
|
|
|
reasonable representation for programs, and text editors and source code |
|
|
|
management systems can all handle it nicely. But a complex ant file can |
|
|
|
get ugly because XML is a bit ugly, and a complex build is, well, |
|
|
|
complicated. Use XML comments so that the file you wrote last month |
|
|
|
still makes sense when you get back to it, and use Antidote to edit the |
|
|
|
files if you prefer it. |
|
|
|
|
|
|
|
|
|
|
|
<h2>Endpiece</h2> |
|
|
|
|
|
|
|
Software development is meant to be fun. Being in the maelstrom of a |
|
|
|
tight project with the stress of integration and trying to code |
|
|
|
everything up for an insane deadline can be fun -it is certainly |
|
|
|
exhilirating. Adding a bit of automation to the process may make things |
|
|
|
less chaotic, and bit less entertaining, but it is a start to putting |
|
|
|
you in control of your development process. You can still have fun, you |
|
|
|
should just have less to worry about, a shorter build/test/deploy cycle |
|
|
|
and more time to spend on feature creep or important things like skiing. |
|
|
|
So get out there and have fun! |
|
|
|
|
|
|
|
<a name="reading"> |
|
|
|
<h2>Further Reading</h2> |
|
|
|
</a> |
|
|
|
<ul> |
|
|
|
<li> |
|
|
|
<a |
|
|
|
href="http://www.martinfowler.com/articles/continuousIntegration.html"> |
|
|
|
Continuous Integration</a>; Martin Fowler. <br> |
|
|
|
A paper on using ant within a software project |
|
|
|
running a continuous integration/testing proces. |
|
|
|
<li> Refactoring; Martin Fowler, ISBN: 0201485672 <br> |
|
|
|
Covers JUnit as well as tactics for making some headway with the mess of |
|
|
|
code you will soon have. |
|
|
|
|
|
|
|
</ul> |
|
|
|
<hr> |
|
|
|
<p align="center">Copyright © 2000 Apache Software Foundation. All rights |
|
|
|
Reserved.</p> |
|
|
|
|
|
|
|
|