| <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 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"> |
| %IncludeBuildCore; |
| %IncludeBuildSecondary; |
| ]> |
| |
| <target name="includedBuild"> |
| &IncludeBuildCore; |
| &IncludeBuildSecondary; |
| </target> |
| </pre> |
| The clean 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. |
| <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> |
| |
| |