I've got a little project I'm working on where I've got an XSLT file that produces an SVG image that I subsequently want to rasterize with Batik. There's also a couple other resources that get built along with that. I've used Batik before for this task and I was impressed. The thing is, I had some long command line I'd set up to use it. While I like the fact that I can just type in what I want to do in the case of a one-off project, it bothers me when I have to go back and re-learn how to use a tool because I don't remember all the parameters that I used.
A build tool is a great way to parameterize what you're doing and keep track of the steps you followed. A build tool can be part of your IDE, it can be a traditional tool like the venerable make, or it can just be a batch file. I've tried all these routes in the past and each has pros and cons. Make is a great tool because it can do so much and is well-suited to the kinds of work that it automates. The makefile also serves as an artifact that details how a build happens for a given target in a given project. Of course the syntax of a makefile can be cryptic for advanced cases and the whitespace issues can be tricky even in simple cases. I was told by an old Unix hack once that there was only ever one makefile - every other one was copied off of that one.
So some clever wag came up with the Ant build tool. It's cross-platform and doesn't have some of the quirks that make does. I'm sure it has it's own, but I haven't seen them yet so I can be optimistic.
Since I'm developing this particular project in Eclipse and Eclipse comes with Apache Ant, I thought this would be a great opportunity to try it out. I want to see how hard it will be to have Ant handle my simple project needs and how complex or simple the build files that it uses are. I know how easy it is to write a batch file that just rebuilds everything, and such a batch file is a simple artifact that records the exact build steps. I hope that using Ant will make my projects scale up more easily than that. When adding new files to a batch-driven project, build times always go up and batch files get very ugly very quickly.
Comparing to a batch file puts the bar pretty low. Let's see how my Eclipse/Ant combo compares.
As a starting point I've got the project that I mentioned above and I want to orchestrate two steps (so far) by telling Eclipse to build the project. I want it to perform the transform by applying sprite.xslt to driver.xml. This will produce spritesheet.svg and demo.html. Next I want to take spritesheet.svg and rasterize it to create spritesheet.png. The raster image, spritesheet.png is referenced by demo.html.
The transform step is to be performed using Saxon 8 and the rasterization step is to be done with Apache Batik. I was originally going to use Apache Xalan for the transform, but there are a couple XSLT2 features that I want to use.
I don't think it should make a difference here, but the project files are all stored in a Subversion repository and checked out into the Eclipse IDE using the Subclipse plugin. So Tigris gets some love too.
Setting up the Ant Build
I happen to know (I've tried this more than once) that Eclipse will want the Ant buildfile to be available when I try to set up the build. So I'm going to create an XML file as part of my project based on the sample buildfile in the Ant manual. Since I've got to create a buildfile, I'm going to diverge here for a little bit and describe what I did to make it.
First off, in Eclipse, in the Navigator or Resource view, right click on the project name and choose New -> File. For a file name I typed build.xml - that's the default name of an Ant buildfile. Click the Finish button and there's a blank XML file in the editor pane. I pasted in the contents of the example buildfile as a starting point. It's short at just 38 lines and I know I won't need all those.
Skimming the code I saw tags with names like "javac" and "mkdir" so I started to worry. In the manual though, it describes that the tags I saw are tasks to Ant. Tasks make up the contents of a target. Targets in Ant sound like they're analogous to build targets in a makefile. The XML notation makes Ant targets a lot more clear of course.
Common makefile targets get names like "all", "clean" and "configure". In general a target is a set of tasks to perform. The lineage of the term "target" comes from the fact that the tasks performed during a build have the intent of producing a certain target. Um, that's target like in cp [source] [target]. A target could be the Intel version of a program instead of the PowerPC version. A target could be the client version of an application instead of the server version. What constitutes a target in your project is up to you. My target is going to be called "spriteDemo". The tasks for that target should correspond exactly to the description I gave above of the build I want to perform from Eclipse eventually.
I started by replacing the compile target with my new "spriteDemo" target. I don't need to compile any Java, I need to perform a transform. Luckily for me, I see that Ant has a built in task called Style (also called xslt) for exactly this purpose.
[fast forward through three painful, mind-numbingly monotonous days of wrestling with classpaths]
Style seems like it would be great if I were using Apache Xalan to transform XSLT version 1. The style task would also be great if there were a sensible way to specify your XSLT processor, instead of relying on seemingly random interpretations of the classpath. I'm sure that I managed to get this (the style task) to work on one computer by setting the classpath environment variable appropriately, then running the ant.bat file from the Ant 1.6.5 that comes with Eclipse 3.1. I can't repeat that behaviour on another machine though, and that goes totally against the advantage I'm looking for with a build management tool (portability and archivability of the build).
What I ended up doing, and it seems to work okay, was using an Ant
<a href="http://ant.apache.org/manual/">java task</a> to execute Saxon just as I had from the command line (in build.xml):
argvalues are arguments passed to Saxon. The
classpathsection sets the classpath for calling Saxon. This stuff is more machine-dependent than I'd like, but I think the machine-dependency can be reduced a whole lot as I learn more about Ant.
Since that worked so well, I modeled my rasterization step off the same idea. The rasterization is handled by a target with a
java task that calls the Batik rasterizer (a sample application available with Batik). Here's the code from build.xml:
Again, I don't know that this is perfect, I just know that it just works for me right now.
Creating the Eclipse Builder
While working on my Ant buildfile, I did testing in a command shell (DOS prompt, whatever). Since I'm using the version of Ant that came with Eclipse, I had to add a couple environment variables. In Windows, I set ANT_HOME=C:\eclipse\plugins\org.apache.ant_1.6.5 and I set PATH=%PATH%;%ANT_HOME%\bin. JAVA_HOME is already set and c:\eclipse is my Eclipse install directory (you can either set these every time on the command line or just go to the Advanced tab of the System dialog in your control panel and fill them in there). After adding the environment variables I could type "ant" in the project directory and have it run outside Eclipse. I wouldn't need to set these if I were working only in Eclipse.
Okay, so I have a working Ant build.xml. Now, step by step, here's what I'm doing. In the Eclipse Package Explorer View, right click on the project and choose Properties. In the Properties dialog that appears, choose Builders on the left pane. My list of builders for this project is empty. On the right side, click New... and a "Choose Configuration Type" dialog pops up that lists a few options including Ant Build and Program. I choose Ant Build and click Okay.
Now I get the really big dialog. It's titled "Properties for New_Builder" because there's a spot to enter a name for the builder. It defaults to New_Builder, but I'll call mine Bob. There's a row of tabs with a bunch of options on each. All I want to set initially is the Buildfile on the Main tab. I chose "Browse Workspace..." and from there I picked build.xml from the files in my project. That's all I needed to set for my case; I clicked "OK" after that and my build worked.
To run the build, I can click the Build button on the toolbar or pick Project -> Build off the Eclipse menus. There's also an Ant view available that I added my build.xml to. To see the Ant View, I chose Window -> Open View -> Ant. Then I right-clicked inside that view's pane and chose "Add Buildfiles..." This gave me a Buildfile Selection window that I chose my build.xml from. Now there's a tree view of the different targets in my buildfile shown in the Ant view of Eclipse. I can double-click a target and it builds. This sounds kind of like the functionality Antelope describes.
So now I can use Ant through Eclipse to call my XML/SVG transform and rasterization tools as well as editing all the files in my project, and maintaining the source by integrating with Subversion (via Subclipse). And so my fragmented development environment gets much more integrated. All-in-all a pleasant experience, but I'd really welcome some simplification of getting an XSLT2 processor running in Ant.