Ant as a Scripting Language

Duncan, the original author of Ant, blogs about the origins of Ant and the addition of script features, primarily the if attribute on the element. Check it out and follow the links for some interesting discussions (although note that the Mike Cannon-Brookes page crashes my Mozilla).

Although misidentified by Duncan, someone does state there that “ANT is the absolute worst.”. Ant wasn’t supposed to be a scripting language but without those features, would Ant have been able to cope with the spectrum of build scenarios that it does today? Is a simple declarative build description powerful enough? I suspect it isn’t. Maybe it is and we just haven’t come across the right way to express the build complexity. The question is how to provide the power required in an elegant manner, without turning Ant into an XML scripting language?

My typical approach is to move complexity into tasks. My original contributions to Ant were tasks for building EJBs because I didn’t like how I had to build them using Ant’s build files and available task primitives. Tasks that express iteration, such as apply are also examples of successfully moving the control complexity into tasks. Yet, it seems Ant user’s don’t want to create tasks so much – they prefer to put the complexity right into their build files. What is the balance between a <doConorsPistonProjectBuild> task and a build file full of complexity?

Today we also have script-like tasks such as foreach possible (though not part of the Ant distribution), and the <script> task for embedded scriptlets. If you wish to, you can write pretty much arbitrary complex logic using Ant. I don’t encourage it.

So, the question is, how should it be done? How can the power be provided for dealing with complex build situations without ending up with a scripting language? Or, is a scripting language the real answer? How would the structure of a build then be expressed? I don’t know. I continue to dislike the addition of if and failonerror attributes to every task but I’m not sure how to meet the needs of the users who want these.

If you wanted the perfect build system today, unconstrained by compatibility, current mindset or other issues, what would it look like? Would it be like make, like Ant or something different? How would it describe a build, how would it deal with the arbitrarily complex operations that seem to be required in some builds?

Let me know what you think.

Maven v Ant Article

IBM Developer works site has an article on Maven (via Sam Ruby)

It’s an interesting article (although the layout on Mozilla is a little strange). It includes a comparison between Maven and Ant. I don’t agree with everything Charles has to say but that’s probably due to my mindset – you should make up your own mind. He is right that Maven and Ant target different aspects of the build process (or problem as he calls it). I tend to think of Maven as an Ant 4GL.

I haven’t had time to really study how Maven works. Maybe when it goes to 1.0 I’ll set aside some time and try to write up some thoughts.

How to Clover Ant

Clovering Ant is a little more complicated that clovering a regular Java project because Clover itself is running within Ant as a compiler adapter. We only want the Clovered Ant to be used for the test run. All other Ant operations needs to be done with a non-clovered Ant, or they’ll affect the results.

Luckily the standard build system for Ant works this way anyway. When Ant is built, a bootstrap version of Ant is built to actually do the full Ant build. We can use the bootstrap Ant as the non-clovered Ant to clover the main Ant build.

I have an Ant build file, clover.xml, which does everything for me. The steps are

  1. bootstrap Ant
  2. build -f clover.xml complete

In the second step, there are a few other targets we can use besides the "complete" target. These give different variations.

I’ll briefly explain each of the targets in the build.

  • The taskdefs define the ant-contrib and clover tasks. The ant-contrib foreach task is only used in the generation of historical data. This only has to be done once
  • setup – sets up the clover properties with the clover-setup task.
  • clover – This target does the work for a single clover run. The ant tasks clean up any old builds, build the code and build the test code. The clean and test code builds do not inherit properties preventing the clover build.compiler value from affecting these operations. The build operation on the other hand picks up the clover properties and references, so that the build.compiler property is set in the sub-build, thereby enabling Clover in the compilation. The current Ant installation is then removed. Before you use this build, your should obviously make sure it is OK to remove the current installation of Ant. Any optional libraries are copied to the install and the rest of Ant installed with the final Ant call. Once the clovered Ant is installed, it is used to run the Ant test suite, generating the clover database
  • core, all – these two targets are similar to the clover target. The differences are that these targets, clean out the clover database and also generate a clover history point at the end of the run. Additionally, the core target has a patternset so that it only clovers the Ant core, leaving out the optional tasks.
  • complete – sets the date for the history generation to the current date, does a core run, a full run and then generates the reports.
  • report – this target generates three Clover reports. It starts by setting up a common format to be used by all the reports and then generating the historical and current reports.
  • generate-history – this target uses the coreach task to generate a history point for a set of dates. The list includes a point for each month back to 2001.
  • genfordate – this does the generation of a single history point. It uses the date of the history point to checkout the version of Ant from CVS appropriate to the date and then uses the "core" and "all" targets for the actual test run.

If you are using the generate-history target you will not be able to use to do the build because CVS updates will continually change it. You will need to make a copy of the script prior to the build and use that copy instead.

It was pretty interesting to run this and watch a few years of Ant development come and go in a few hours. It’s also impressive that this same basic setup can work back to early 2001. It’s not perfect, of course, since some things (such as test.haltonfailure) only work on more recent builds.

When you are finished, you’ll want to do a final CVS update to get back to the current HEAD version.

That’s all there is to clovering Ant. The principles should be applicable to other projects, especially the generation of the historical reports.

Ant Test Coverage

I’ve clovered the lastest Ant code from CVS and uploaded the results. This shows the coverage for the full source code. I’ve also updated the historical results I uploaded earlier.

I’ll try to upload this regularly to show the coverage of Ant over time as I’d really like to improve the coverage in Ant.

Tomorrow, I’ll explain how I go about clovering Ant and how I generated the historical reports – that involved a few tricks.

Disclaimer: I am employed by Cortex eBusiness, the publishers of Clover.

Ant Configuration Unknowns

I haven’t blogged for a while as I have been writing up an advanced Ant tutorial on Ant Configuration.

This tutorial is an in-depth walk-through of the process through which Ant takes an XML representation of a build file, creates the apprpriate objects and calls the appropriate methods.

Writing the article took a bit longer than I thought as I realised I needed to explain the history of how Ant’s configuration system came about. I also found and fixed a few bugs in the Ant 1.6 process as I was writing this. In fact, I actually started to write this as I was working on a bug. I needed to get a good understanding of the configuration process for myself.

I whipped up some diagrams for this using Dia. They are pretty poor and I may replace them when I get time but for now they may help a little.

I’m hoping this tutorial will help task writers understand the process and potentially to create more definitional tasks. I have some ideas myself …