|
- <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
- </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, maybe with some legacy cruft on the edges.
-
- <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,
- late 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="manual/CoreTasks/ant.html">ant</a>
- task. For example. the clean target could be handed down to the <tt>intf</tt> and
- <tt>impl</tt> 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>
-
- If you give targets a <tt>description</tt> tag, then calling <tt>ant
- -projecthelp</tt> will list all tasks with their description as 'main targets', and
- all tasks without a description as subtargets. Describing all your
- entry points is therefore very useful, even before a project becomes big and complicated.
-
- <h3>
- Extend ant through new tasks
- </h3>
-
- If ant does not do what you want, you can use the
- <a href="manual/CoreTasks/exec.html">exec</a> and
- <a href="manual/CoreTasks/java.html">java</a> tasks or
- <a href="manual/OptionalTasks/script.html">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="manual/OptionalTasks/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= "manual/CoreTasks/java.html">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. The Junit extensions such as
- <a href="http://httpunit.sourceforge.net/">HttpUnit</a> for web pages, and
- <a href="http://jakarta.apache.org/cactus/">Cactus</a> for J2EE and servlet
- testing help to expand the testing framework. To test properly you will still
- need to invest a lot of effort in getting these to work with your project, and
- deriving great unit, system and regression tests -but your customers will love
- you for shipping software that works.
-
-
- <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="manual/CoreTasks/exec.html">Exec</a>/ <a href=
- "manual/CoreTasks/apply.html">Apply</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>.
- <p>
- 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>
- There is also the <a
- href="manual/CoreTasks/pathconvert.html">PathConvert</a> task which
- can put a fully resolved path into a property. Why do that? Because then
- you can use that path in other ways -such as pass it as a parameter to
- some application you are calling, or use the replace task to patch it
- into a localised shell script or batch file.
- <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, 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= "manual/CoreTasks/chmod.html">
- 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="manual/CoreTasks/get.html">Get<a>, <a
- href="manual/CoreTasks/touch.html">Touch</a> and <A href="manual/CoreTasks/unzip.html">
- 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="manual/CoreTasks/jar.html">Jar</a>, <a href= "manual/CoreTasks/tar.html">
- Tar</a> or <a href="manual/CoreTasks/zip.html">Zip</a> files for deployment, while
- the <a href="manual/CoreTasks/war.html">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=
- "manual/OptionalTasks/cab.html">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=
- "manual/CoreTasks/fixcrlf.html">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. Rumour has it
- that there is such a task in the jakarta-slide libraries.
-
- <p>
-
- EJB deployment is aided by the <a href="manual/OptionalTasks/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="manual/CoreTasks/copy.html">Copy</a> and <a href =
- "index.html#copydir">Copydir</a> , or just sending them to a person or
- process using <a href= "manual/CoreTasks/mail.html">Mail</a> or the attachment
- aware <a href= "manual/OptionalTasks/mimemail.html">MimeMail</a>.
- In one project our team even used ant to build CD images through a build followed
- by a long set of Copy tasks, which worked surprisingly well.
- <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. All the jakarta projects follow a roughly similar
- style, which makes it easy to navigate around one form one project to
- another, and easy to clean up when desired.
-
- <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 <i>in a heirarchy which matches
- the package names<i>. The dependency compilation of javac requires this.
- </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. These can go under source
- too, with a <tt>metadata</tt> directory for web.xml and similar
- manifests, and a <tt>web</tt> folder for web content -JSP, html, images
- and so on. Keeping the content in this folder (or sub heirarchy)
- together makes it easier to test links before deployment. The actual
- production of a deployment image -such as a war file- can be left to the
- appropriate ant task: there is no need to completely model your source tree
- upon the deployment heirarchy.
- <p>
-
- 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.
- <p>
- The only way to retain control over a fairly loosely integrated
- collection of projects is to have a fully automated build
- and test process which verifies that everything is still compatible. Sam
- Ruby runs one for all the apache java libraries and emails everyone when
- something breaks; your own project may be able to make use of
- <A href="http://cruisecontrol.sourceforge.net/">Cruise Control</a> for
- an automated, continuous, background build process.
-
- <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. The final benefit of being
- involved with the process is that it makes it easier for your tasks to
- be added with the ant CVS tree, bringing forward the date when ant has
- taken on all the changes you needed to make to get your project to work.
- If that happens you can revert to an official ant release, and get on
- with all the other crises.
-
- <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="install">
- <h2>
- Installing with Ant.
- </h2>
- </a>
-
- Because ant can read environment variables, copy, unzip and delete files
- and make java and OS calls, it can be used for simple installation
- tasks. For example, an installer for tomcat could extract the
- environment variable TOMCAT_HOME, stop tomcat running, and copy a war
- file to TOMCAT_HOME/webapps. It could even start tomcat again, but the
- build wouldn't complete until tomcat exited, which is probably not what
- was wanted.
-
- <p>
-
- The advantage of using ant is firstly that the same install targets
- can be used from your local build files (via an <tt>ant</tt> invocation
- of the install.xml file), and secondly that a basic install target is
- quite easy to write. The disadvantages of this approach are that the
- destination must have an up to date version of ant correctly
- pre-installed, and ant doesn't allow you to handle failures well -and a
- good installer is all about handling when things go wrong, from files
- being in use to jar versions being different. This means that ant is not
- suited for shrink wrapped software, but it does work for deployment and
- installation to your local servers.
-
- <p>
-
- One major build project I was involved in had an ant install build file
- for the bluestone application server, which would shutdown all four
- instances of the app server on a single machine, copy the new version of
- the war file (with datestamp and buildstamp) to an archive directory,
- clean up the current deployed version of the war and then install the
- new version. Because bluestone restarted JVMs on demand, this script was
- all you needed for web service deployment. On the systems behind the
- firewall, we upped the ante in the deployment process by using the ftp
- task to copy out the war and build files, then the telnet task to
- remotely invoke the build file. The result was we had automated
- recompile and redeploy to local servers from inside our IDE (Jedit) or
- the command line, which was simply invalualbe.
-
- <p>
-
- One extra trick I added later was a junit test case to run through
- the install check list. With tests to verify access permissions on network
- drives, approximate clock synchronisation between servers, DNS functionality,
- ability to spawn executables and all the other trouble spots
- , the install script could automatically do
- a system health test during install time and report problems. [The same tests
- could also be invoked from a JMX MBean, but that's another story].
- <p>
-
- So, ant is not a substitute for a real installer tool, except in the
- special case of servers you control, but in that context it does let
- you integrate remote installation with your build.
- <a name="tips">
- <h2>
- Tips and Tricks</h2>
- </a>
- <dl>
- <dt><b>
- get
- </b><dd>
-
- The <a href="manual/CoreTasks/get.html">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=
- "manual/OptionalTasks/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, does dependency checking and has better error
- messages (usually). Get it. Then set
- build.compiler to "jikes" for it to be used in your build files.
- Doing this explicitly in your build files is a bit dubious as it requires the
- whole team (and sub projects) to be using jikes too -something you can only
- control in small, closed source projects. But if you set
- <tt>ANT_OPTS = -Dbuild.compiler=jikes</tt>
- in your environment, then all your builds on your system will use
- Jikes automatically, while others can choose their own compiler, or let
- ant choose whichever is appropriate for the current version of Java.
-
- <dt><b>
- #include targets to simplify multi build.xml projects
- </b><dd>
-
- You can import XML files into a build file using the XML parser itself.
- 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++.
-
- <p>
-
- There are two inclusion mechanisms, an ugly one for all parsers and a
- clean one. For now, the ugly
- method is the most portable:-
- <pre>
- <!DOCTYPE project [
- <!ENTITY IncludeBuildCore SYSTEM "buildCore.xml">
- <!ENTITY IncludeBuildSecondary SYSTEM "buildSecondary.xml">
- ]>
-
- <target name="includedBuild">
- &IncludeBuildCore;
- &IncludeBuildSecondary;
- </target>
- </pre>
- The cleaner method using XInclude/Xpath will let you include named
- targets from one build file or another, using
- <a href="http://www.w3.org/XML/Linking">
- the xpointer syntax</a>. You'll need to wait for the W3C proposals
- to finalise and the java XML parsers to implement it before
- using xpointer references.
- <p>
- Before you go overboard with using XML inclusion, note that the <tt>ant</tt> task lets
- you call any target in any other build file -with all your property settings propagating down to
- that target. So you can actually have a suite of utility targets -"deploy-to-stack-a", "email-to-team",
- "cleanup-installation" which can be called from any of your main build files, perhaps with subtly changed
- parameters. Indeed, after a couple of projects you may be able to create a re-usable core build file which
- contains the core targets of a basic java development project -compile, debug, deploy- which project specific
- build files call with their own settings. If you can achive this then
- you are definately making your way up the software maturity ladder. NB,
- <tt>ant</tt> copies all your properties unless the <i>inheritall</i> attribute is set to false. Before that
- attribute existed you had to carefully name all property definitions in all build files to prevent unintentional
- overwriting of the invoked property by that of the caller, now you just have to remember to set
- <tt>inheritall="false"</tt> on all uses of the ant task.
-
-
- <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="manual/CoreTasks/style.html">Style</a> task controlling
- the transform. This is the current recommended strategy for creating
- complex build files dynamically. However, its use is still apparently
- quite rare -which means you will be on the bleeding edge of technology.
-
-
- <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.
-
- <dt><b>
- Use the replace task to programmatic modify text files in your project.
- </b><dd>
- Imagine your project has some source files -BAT files, ASP pages (!), anything
- which needs to be statically customised at compile time for particular
- installations, such driven from some properties of the project such as JVM options, or the URL
- to direct errors too. The replace task can be used to modify files, substituting text and creating
- versions customised for that build or destination. Of course, per-destination customisation
- should be delayed until installation, but if you are using ant for the remote installation
- that suddenly becomes feasible.
-
- <dt><b>
- Use the mailing lists
- </b><dd>
- There are two
- <a href="http://jakarta.apache.org/site/mail.html">mailing lists</a>
- related to ant, ant-user and ant-developer. Ant user is where <i>all</i>
- questions related to using ant should go. Installation, syntax, code
- samples, etc -post your questions there or search the archives for
- whether the query has been posted and answered before. Ant-developer
- is where ant development takes place -so it is <i>not</i> the place to
- post things like "I get a compilation error when I build my project" or
- "how do I make a zip file". If you are actually extending ant, on the other
- hand, it is the ideal place to ask questions about how to add new tasks, make
- changes to existing ones -and to post the results of your work, if you want them
- incorporated into the ant source tree.
-
- </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. Antcall is the trick here, as it allows you to have two paths
- of property initialisation in a build file.
-
- <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 isn't 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.
-
- <h3>Big projects still get complicated fast</h3>
-
- Large software projects create their own complexity, with inter-dependent
- libraries, long test cycles, hard deployment processes and a multitude of
- people each working on their own bit of the solution. That's even before
- the deadlines loom close, the integration problems become insurmountable,
- weekends become indistinguishable from weekdays in terms of workload and
- half the team stops talking to the other half. Ant may simplify the
- build and test process, and can eliminate the full time 'makefile engineer'
- role, but that doesn't mean that someone can stop 'owning the build'.
- Being in charge of the build has to mean more than they type 'ant all' on
- their system, it means they need to set the standards of what build tools to
- use, what the common targets, what property names and files should be
- and generally oversee the sub projects build processes. On a small project,
- you don't need to do that -but remember: small projects become big projects
- when you aren't looking. If you start off with a little bit of process, then
- you can scale it if needed. Ff you start with none, by the time you need
- it it will be too late.
-
- <h3>You still need all the other foundational bits of a software
- project</h3>
-
- If you don't have an source code management system, you are going to end
- up hosed. If you don't have everything under SCM, including web pages,
- dependent jars, installation files, you are still going to end up hosed,
- it's just a question of when it's going to happen.
- CVS is effectively free and works well with ant, but Sourcesafe, Perforce,
- Clearcase and StarTeam also have ant tasks. These tasks
- let you have auto-incrementing build counters, and automated file
- update processes.
-
- <p>
-
- You also need some kind of change control process, to resist
- uncontrolled feature creep. Bugzilla is a simple and low cost tool for
- this, using ant and a continuous test process enables a rapid evolution of code
- to adapt to those changes which are inevitable.
-
- <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>
-
- <a name="author">
- <h3>About the Author</h3>
- </a>
-
- Steve Loughran is a research scientist at a corporate R&D lab,
- currently on a sabbatical building production web services against
- implausible deadlines for the fun of it. Because of those implausible
- deadlines, email questions related to this document are generally, and
- regretfully unwelcome, unless they are corrections to the content,
- advanced discourse on how to evolve software engineering processes to
- meet the next generation of challenges, or from someone he knows. Even
- then, a timely response is unlikely. Please use the mailing lists
- instead.
-
- <hr>
- <p align="center">Copyright © 2000, 2001 Apache Software Foundation. All rights
- Reserved.</p>
- </body>
|