Getting to know Ant: Part I
To me, some of the most fascinating problems are the ones that are only visible in hindsight. The angled measuring cup might be the best example of this. With a standard measuring cup, you have to bend over or lift the cup to see how much of a substance you've measured. On the other hand, the angled measuring cup can be read while standing upright. Yet when asked, most people didn't realize the problem with a normal measuring cup until after having seen the one from Oxo.
In much the same way, we ran across a “hindsight problem” at work: every week one guy had to take an hour or two out of his schedule in order to produce an new build for people to test. At the time it seemed perfectly acceptable. Then came the automated build. Now, in hindsight, it's obvious that we allowed several man weeks of a good engineer's time to go to a complete waste. Not only that, but we wasted the time of several testers in the process as well. The same exact set of instructions could be (and were) used to make every build. No part of the build process required any decision that couldn't be scripted to work faster and more consistently.
In order to once and for all save man-kind from this time-sink (or at least a smaller sub-set of humanity), I'll be doing several posts of the process of creating an build script. Though I'm starting with the basics now, by the end of the series I'll probably spend a little time focusing on how to build Flex and .NET projects without having to require any (expensive) human interaction. Before we dive into code, you'll need to install a Java runtime and Apache Ant. Once you've done that, we'll be ready to start.1
One of the first concepts that has to be grappled with is that we are going to be giving all of our commands through XML. Though most engineers are doubtlessly familiar with storing data in XML, the concept of writing XML that will be executed might be a little more difficult to accept. Thankfully, this feeling passes rather quickly. Enter the following code snippet into a plain-text editor and save the file as build.xml. 2
<project name="demo" default="hello" description="Our first ant project"> <target name="hello" description="Perform the ancient ritual of computer science."> <echo>Hello World.</echo> </target> </project>
In order to avoid angering the sages of computer science, we've started with a simple hello world script. To try it out, jump to the command-line, change to the directory that you've stored your script in and run “ant”. At that point you should be greeted with a “Hello World.” So, what did we actually do? Before examining out script, there are a few terms that we need to become familiar with. The three that we should start with are “project”, “target”, and “task”. For our purposes, projects and targets are roughly the same as classes and methods, respectively. Tasks are our command set. They are the actual description of what we want done.
So what did we actually do? We started by creating a new project that we named demo. We also told ant that if it isn't told to run a specific target, it should find and execute the target named “hello”. Lastly, we created a target named “hello” that has the job of printing “Hello World.” Now that we've gotten our first ant script out of the way, let's add one last concept to it.
<project name="demo" default="printWorld" description="Our first ant project"> <target name="printWorld" description="Print world!" depends="printHello"> <echo>World</echo> </target> <target name="printHello" description="Print hello!"> <echo>Hello</echo> </target> </project>
If you save and run this, you'll see that it prints “Hello World” again, albeit broken up on separate lines. Though our project only specified that we wanted to execute “printWorld” by default, the addition of “depends” added a dependency on printHello. Thus, before printWorld could execute, printHello had to successfully execute. In this case, there any real danger of printHello failing. However, had it contained tasks which had failed, such as compilation or IO, printWorld would have never executed. In fact, our script execution would have stopped.
In the next post, we'll actually look at some other tasks that we might want to use other than just “echo”, as well as covering a brief introduction to variables.3 If you have any questions / comments / corrections, please don't hesitate to post them below.
Ant isn't the only available option for a build script. There is Nant, it's .NET counter-part, and Maven amongst others. Ant is simply the one that I have the greatest familiarity with. ↩︎
Though not strictly required to be named build.xml, it is the default that ant looks for. Use of a different name would require an extra command-line parameter. And deviation from standard. ↩︎
Edit: After posting this, I've decided to temporarily postpone variables so that I can spend more time on them. ↩︎