| By Joey Gibson | Article Rating: |
|
| November 1, 2002 12:00 AM EST | Reads: |
18,068 |
The Basics
Ant is very similar to the standard Unix tool "make" that just about
every experienced C programmer is familiar with. It does its work based on a
build file, typically called build.xml, that tells Ant how and what to
build. The contents of the build file are marked up in XML, making it rather
self-explanatory. Different actions are triggered by aptly named XML tags
with attributes and subtags detailing the work to be done.
Listing 1 contains an extremely simple build file. First I'll show how to tell Ant to use this file from the command line and what the output will be, then I'll dissect the file, explaining the different parts. To get us moving a "task" is a basic unit of work and a "target" is a grouping of tasks that does something useful. Your build file will consist of several targets, each containing one or more tasks. Targets, in turn, are contained in a single "project." I'll explain these concepts shortly, but now let's run this thing and see what happens! (The source code for this article can be downloaded from www.sys-con.com/java/sourcec.cfm.)
Running Ant
Running Ant is simply a matter of invoking the shell script or batch
file that came with the Ant distribution. When you execute this file with no
command-line arguments, Ant generally looks in the current directory for a
file called build.xml. If it finds this file, it will execute the default
target specified in it. Figure 1 shows what happens when we execute Ant.bat
with no command-line parameters.
Notice that Ant tells you which targets are being executed (the left-aligned text followed by a colon) and which task within a target it's working on (the word inside the brackets). This gives you a "progress meter" of the build. Also notice that even though we didn't tell Ant which target to run, it executed our JAR target, which is specified as the default target inside the build file.
You can also tell Ant which targets you want it to execute and the order. Most build files will contain a target called clean that removes any artifacts from previous builds and "resets" the project. It's not uncommon to run this clean task just before rebuilding the project. For our example this can be accomplished by specifying the command line:
ant clean jar
Figure 2 shows the output from executing this command line. Pay special attention to the order of the targets that are executed.
Ant also supports a command-line switch that tells it where to find a build file to use. This switch has the intuitive name of buildfile and takes a pathname to the file that will serve as the build file. Using this switch, you're no longer required to name your build file build.xml, and it obviously doesn't have to be in the current directory. As you'll see, this is where the basedir attribute of the <project> tag comes in handy. If you set it to "." or didn't specify it, all the relative path information will be handled properly, since the dot means "relative to the build file." This is generally what you want.
If your build file is living in a directory that has a name similar to "build" and the source and compile directories are siblings of the "build" directory, then you would need to set basedir equal to the parent directory or "..".
The Build File
The Ant build file is an XML document that tells Ant how to do the work
to build a project. The first line in Listing 1 is the standard XML
processing instruction that tells the XML parser which version of XML this
document complies with (since there's currently only one version of XML,
this line will always be set to version 1.0).
The <project> Tag
Line 3 is where the interesting content begins. The <project> tag is the
only top-level tag that is allowed in a build file. In this example the
<project> tag defines a logical name for this project (the name attribute)
and specifies a default target (the default attribute) and a base directory
for relative path specifications (the basedir attribute).
The name is not really used anywhere with an out-of-the-box Ant installation, but integrated development environments that understand and integrate with Ant will use the name to differentiate between different projects. Examples of Ant-aware IDEs include Eclipse, jEdit, and IntelliJ IDEA (URLs are provided at the end of the article).
The default attribute tells Ant which target to execute if you don't specify one on the command line. In general, the default target should be set to the one that's most useful or the one you execute the most; this will save some typing later on. In our case we want everything to execute, so we'll set the JAR target as the default.
The basedir attribute is used when building up relative pathnames. There are many properties set in a typical build file that specify directories or files. It's much easier and portable to specify these in a relative rather than absolute fashion. In other words, using the basedir attribute will allow you to pick up and move your entire build directory structure to a different disk or machine, without radically changing your build file. This is a big win, especially in a multideveloper scenario where different developers may not have the project directory in the same place on their machines.
Setting Properties
Just as with make, it's useful and indeed encouraged to set constants
for often-used information to avoid retyping and copying. This is
accomplished with the <property> tag that can appear either by itself
directly inside the <project> tag or inside a <target> tag. The <property>
tag has several options but we'll consider only one here: file. Supplying a
file name (which will be found relative to the basedir attribute if no path
is given) will create properties for each line in the file. The following is
the properties file that we're using for this project.
This is standard Java properties syntax. We are defining four
properties, one of which is based on one other; the jar.name property on
line 3 is based on the projectname property on line 1. The ${} syntax is
Ant's way of dereferencing a property, substituting the property's value.
You'll notice that on lines 9, 13, 14, 18, 19, 24, and 25 of the build file
we use this same syntax the same dereferencing syntax that works in the
properties file works in the build file.
Note that we could have specified each of these properties directly in the build file, but it is much cleaner to move them out to a properties file. This makes the build file less cluttered and the properties a little easier to read.
Defining Targets
The <target> tag is the real workhorse of an Ant build file. Define a
target for each major area of functionality that you need; this generally
consists of some common setup, a compilation setup, a step to create a JAR
file, and perhaps steps to create a WAR or EAR file.
In our example, we have five targets defined: init, prepare, compile, jar, and clean. The init target in our example merely loads up the properties file, as explained in the previous section. There's nothing stopping you from performing other tasks in this target; one common task that you will find in init is a call to <timestamp>, which sets properties containing the current time and date. You'll see an init target in most build files that you examine.
The prepare target is another common target that provides functionality that can be shared by multiple targets. Here the prepare target is simply creating a directory using the built-in task <mkdir> that we can compile our Java source code in. Notice that the directory we ask it to create is the result of using a property. The <prepare> target could do quite a bit more, such as create entire directory hierarchies, but for our purposes, simply creating this one directory is sufficient.
Notice that at the end of line 8 there's an attribute that says depends="init". This attribute sets up a dependency between the current target and the target(s) specified. When Ant gets ready to run our prepare target, it will see that we have a dependency and will then go off to run the depended-upon target(s) and then come back and run ours. This is a powerful mechanism for avoiding redundancy. As build files get larger, you'll end up with many targets that need some common functionality; moving this commonality into a single target and then setting up a dependency allows this to happen. Here we specify that prepare depends on init, which makes sense because prepare uses a property that's set inside init. If init were not called, we'd end up with a directory called ${build.name} being created. (Yes, we could have put the <mkdir> task directly into the compile target or inside init, but then you wouldn't have seen the dependency mechanism in action.)
Next, our compile target does what you might expect: it compiles our code! As you can see from Listing 1, there's a built-in task called <javac>, a wrapper for the standard javac compiler. It has many attributes, most of which are optional. Here we tell it where to find the source code to compile, srcdir="${src.dir}", and where to put the compiled class files, destdir="${build.dir}". Using the task this way will compile all Java source files that it finds in the ${src.dir} directory (and all of its subdirectories) and put the binary class files in the directory specified by the ${build.dir} attribute. If the source files declared a package, then the package structure will be represented in the destination directory.
Notice that the compile target depends on prepare. Since we need the build directory to be created before we try to write class files to it, we need to call prepare. But we also need the properties that get created inside init. Because compile depends on prepare and prepare depends on init, everything will be executed in the proper order and compile will work just fine.
Moving on, our jar target will take the output of our compile step and build a Java archive out of it. This example is almost overkill because of the simplicity of the project, but I wanted to show you a few of the interesting built-in tasks that Ant provides. You can see here that the jar task will build the archive specified by destfile and will include in it any class files (and directory structure) that are returned by the enclosed <fileset>. In this case, it will return only a single class file, but if there were others located anywhere under ${build.dir}, it would also return those. And notice again that it has dependencies. It wouldn't be terribly useful to create a JAR file without first compiling our source files. Thus setting depends="compile" will cause everything to be compiled (and prepared and inited) before trying to create a JAR. Usually if a target fails, the build aborts. There are a few exceptions, but generally this is the rule.
Finally we have a target called clean. This target can be executed to remove all artifacts of previous builds to ensure a clean build. Here we're deleting the compilation directory and the JAR file created from a previous run. Both these deletes will fail silently if the specified file/directory doesn't exist, which is fine. You'll almost certainly want a clean target in most of your build files, but care must be exercised when using the delete task, the same care you exercise any time you're deleting files and directories. It's quite painful if you delete the current directory and its contents instead of a subdirectory. Notice that our clean target depends on init. The reason for this is that if init is not run, then the two properties that are used by the <delete>s would never be defined and nothing would get deleted.
That's About It
That wraps up our discussion of the simple build file (the Hello, World
of the Ant world, if you will). You should now have an understanding of what
a build file looks like, how the different pieces relate to each other, how
to declare that a task is dependent on another, and what a couple of the
built-in tasks are.
When Things Go Awry...
Inevitably you're going to write a build file that you think is perfect,
but when you try to run it your screen will fill up with stack traces and
other error messages. One of the most common errors in a build file is not
properly formatting the XML code. Remember that XML, unlike HTML, requires
all attributes to be quoted and all tags must be closed! The build file in Listing 2
will not parse correctly because there are missing quotes all over the place
and at least one target isn't closed. Even leaving off one quote will cause
your file not to parse properly. An editor that does color syntax
highlighting or checks for well-formed XML will help you spot these errors.
Figure 3 shows the output from running Ant with the bad.xml file in Listing 2.
The parser encounters the first error and indicates it as being on line 5 (the number after the colon next to the file name). Actually it's on line 4, which is where we forgot to add the closing quote to the name attribute of the init target. Since Ant couldn't complete parsing the file, it will abort the run after the first error. Once you add the missing quote and run again, you'll see the next error, an unclosed <property> tag.
Remember that the error messages may not always explicitly help you and, in fact, may be caused by something other than your build file, such as a failed execution of an external program. Get comfortable with Ant's error messages; this is certainly not the last time you'll see one.
Summary
In this article I provided a quick introduction to an extremely useful
tool. You should be able to take what you've learned here and immediately
start applying it to your current business problem. There are a number of
books on Ant available (one of which I coauthored) that would be helpful.
Don't forget that the entire Ant manual is included with the Ant
distribution and is located in ANT_HOME/docs/manual. It's also available on
the Ant home page.
Links
Published November 1, 2002 Reads 18,068
Copyright © 2002 SYS-CON Media, Inc. — All Rights Reserved.
Syndicated stories and blog feeds, all rights reserved by the author.
More Stories By Joey Gibson
Joey Gibson is a senior consultant and instructor for BravePoint, a consulting company located in Atlanta, GA USA. He is the co-author of Ant Developer's Handbook published by SAMS and available October 18, 2002. He can be reached at jgibson@bravepoint.com or joey@joeygibson.com.
![]() |
Nusco 12/12/02 08:20:00 AM EST | |||
One of the most compelling reasons for using Ant is that it makes a whole project easy to migrate amongst workstations, platforms and IDEs. Just look at how many open source projects come with a build.xml file. To build them you just lanuch ant, and you're done. |
||||
![]() |
Ger 11/05/02 12:46:00 PM EST | |||
Some type of document is needed to tell other programmers how to compile the source code. What other classes and or jar files etc. |
||||
![]() |
NRE 11/05/02 12:40:00 PM EST | |||
Seems to me Ant is similar in capability to imake, which allows abstraction of 'make' rules to account for platform, compiler, etc. variances. Not sure what Ant buys you in comparison, aside from a technology face lift. Either tool should be good for a consistent build process and could help manage software releases. |
||||
![]() |
Frank Cooley 11/05/02 11:54:00 AM EST | |||
A lot of us have gotten away from using ide's. Ant simplifies building and distributing (think about web apps and servletds) under those conditions. |
||||
![]() |
Alan W. 11/05/02 10:25:00 AM EST | |||
NB, My $0.02. |
||||
![]() |
N.B. 11/05/02 09:30:00 AM EST | |||
I stopped reading on the 3rd page after not finding a reason WHY to use Ant. Already today JBuilder, Visual Age, Visual cafe, NetBeans, Oracle JDeveloper, etc, all can compile one's code with a simple key press. So I don't see a reason to use Ant in the first place (I'm not being sarchastic, I just don't see the benefit of using such a tool). So, can anyone explain why? |
||||
![]() |
Rajesh Gupta 11/29/02 05:09:00 AM EST | |||
I want to register myself on this site. |
||||
![]() |
Steve Loughran 11/08/02 01:45:00 AM EST | |||
Alan says: I must respectfully disagree. Once you write unit tests and set up ant so that you build and test every time you invoke it you have just used the tool to automate a test-centric development process. Not a build process, a development process. When I see people saying 'I dont need ant', it says to me that these people dont use Junit or siblings yet. A secret goal of Ant is to eliminate the role of 'build person' except on very large projects. Ant is that much easier to use than make that you can have a build process that barely needs maintenance, and which is simple enough for any developer in the team to maintain as the need applies. Looking forward to seeing your book BTW alan, amazon posted it to me today. You never mentioned you were writing it when we were all up in Redmond that week in May, did you? I am still happily confident that Java Development with Ant is better, but I'd like to see what you have to say on the build process. I found the bit in the sample chapter where you deconstruct Ant in Anger quite entertaining already. NB. the reason you need to have a deployment target as well as staging in the build file is that ops should be using ant to automate deployment too. Lets you run post-installation junit tests to validate the configuration, see. |
||||
![]() |
Steve Loughran 11/08/02 01:20:00 AM EST | |||
Firstly, using ant does not mean abandoning and IDE. I have IDEA, jEdit and Forte installed on my machines, and use whichever is appropriate. All of these (and others) provide built in ant support. Using ant no longer ties me to one IDE, and instead gives us a build file that works for everyone without all the customisations it takes to keep IDE managed builds in sync. This is why all open source projects use Ant. Secondly, yes, ant is closest to imake. However it is java based and java centric. It runs on any platform with Java, from a windows PC to an IBM mainframe. So you know both your build system and often your deployment system will be able to run ant. Indeed, tomcat4.1 uses ant internally to build jsp pages. Where ant really excells is the stuff it brings to the table above and beyond pure compliation. Xdoclet can generate all your EJB descriptors, JMX interfaces, Castor XML/SQL bindings from javadoc tags . Junit will run your tests, creates a fancy html report to summarise it. lets you issue SQL statements during the build to set up the DB for testing. And the deployment tasks let you deploy to local or remote servers. It is these extras that really give Ant its power. If you use an IDE you usually have manual stages to do things, or inflexible wizards to create one-off EJB descriptors, XML Schema to object mappings, the things you end up redoing again and again. Use ant: set your self free from all the drudge work. Steve (Ant developer, Axis Developer, co-author Java Development with Ant, Genrral Web Service Hacker) |
||||
- Three Tips to Successfully Load Test Adobe Flex Applications
- Patterns for Building High Performance Applications
- It's the Java vs. C++ Shootout Revisited!
- Asynchronous Logging Using Spring
- Graal, a Dynamic Java Compiler in the Works
- Cross-Platform Mobile Website Development – a Tool Comparison
- Write Once Run Anywhere or Cross Platform Mobile Development Tools
- Three Buzzwords That Every CIO Hears but One They Should Listen To
- Cloud Expo New York: The Java EE 7 Platform - Developing for the Cloud
- Immersing into JavaScript Frameworks
- Workday Reportedly Prepping to Go Public
- Book Review: Sams Teach Yourself Java in 24 Hours
- Three Tips to Successfully Load Test Adobe Flex Applications
- Book Excerpt: Introducing HTML5
- Five Years Waiting for JRE 7: Is It Justified? (Part 1)
- Book Excerpt: Java Application Profiling Tips and Tricks
- i-Technology in 2012: Five Industry Predictions
- Patterns for Building High Performance Applications
- It's the Java vs. C++ Shootout Revisited!
- OpenXava 4.3: Rapid Java Web Development
- The Next Web Architecture
- Asynchronous Logging Using Spring
- Java for Programmers (2nd Edition)
- Graal, a Dynamic Java Compiler in the Works
- A Cup of AJAX? Nay, Just Regular Java Please
- Java Developer's Journal Exclusive: 2006 "JDJ Editors' Choice" Awards
- JavaServer Faces (JSF) vs Struts
- The i-Technology Right Stuff
- Rich Internet Applications with Adobe Flex 2 and Java
- Java vs C++ "Shootout" Revisited
- Bean-Managed Persistence Using a Proxy List
- Reporting Made Easy with JasperReports and Hibernate
- Creating a Pet Store Application with JavaServer Faces, Spring, and Hibernate
- Why Do 'Cool Kids' Choose Ruby or PHP to Build Websites Instead of Java?
- What's New in Eclipse?
- i-Technology Predictions for 2007: Where's It All Headed?



















