What can I say? I love the <import> task. š If the Jolt Awards were accepting nominations at the moment, I’d be nominating that one bit of Ant 1.6 all by itself. š
I’m directly responsible for about half-a-dozen projects at work (though most are dormant), and indirectly responsible for setting guidelines and standards for another dozen or so, with more coming up. One of the more dominant aspect of that is ensuring that the build scripts comply with our (well, my) guidelines. We leverage Ant a lot in our environment, and our common scripts are not at all simple. Besides that standard task of compiling, we use our build scripts to:
- Generate source code (via XDoclet and deployment descriptors
- Package up releases
- Run JUnit tests locally
- Deploy to targetted servers
- Run JUnit tests remotely
- Produce code coverage stats (via Clover)
- Enforce style standards (CheckStyle)
- Produce metric reports (JavaNCSS and JDepend)
- (Soon) Duplication detection (Simian)
- JavaDoc
- A custom ant task to fetch third-party components based on a descriptor
- Link into our continuous build servers (CruiseControl, of course)
- Many more…
As you can imagine, these scripts are reasonably large and somewhat complex. The thing is, however, they’re nearly all the same, for each type of project. Even the couple of projects that are unique have large chunks of commonality. The major differences are classpaths (and even those are often similar!)
Furthermore, these scripts evolve. We only have Clover coverage over a couple of projects at the moment, because it was a pain to get into the scripts (largely due to the need to produce clean deployable builds in the continuous build environment, AND get coverage stats). The duplication checking will go in once my boss signs the purchase order. Then there’s a couple of differences that are a bit more cosmetic. Chasing down all the scripts and retrofitting changes is somewhat time-consuming and often neglected, but it makes it harder when I go back to those projects.
The <import> task in Ant 1.6 is looking to be a saviour. I only started looking at it yesterday, but already I’ve extracted a common set of tasks into a master file and I have two projects sharing it. The project build files are a good fifth of the size they were, and are easy to understand; all they really do is set up the class paths for the build steps, plus packaging (and a couple of unique steps; one project uses JAXB, for example). This has allowed me to integrate Clover into the build script of the second project in about 20 minutes, as a side benefit of switching to the imported script; this compares to the three days it took for the first project, and 1 day for the second (learning curve, I guess). When I roll out Simian, it will be a change in one or two core scripts, and everyone else will get it.
The best part is that I don’t even have to sacrifice flexibility. The “child” build scripts have complete control over what features they take from the parent and what they override. About the only change I’ll have to make is to make some of my tasks a bit more fine grained, so that overridden targets don’t have to bring in extra stuff.
The most impressive part, of course, is that I can now print off the build script on 1 sheet of paper (admittedly a double-sided 2-up sheet, but hey). Oh, and I can easily differentiate on what is unique to the project and what is standard. Now, if I can only figure this into my reuse metric… š
When Ant 1.6.2 comes out, and the JUnit task has the forkmode option, I’ll be really happy. š