Ant is a simple, effective tool that can guide you toward a solid build infrastructure.
In last week's article, I introduced the problem of a convoluted build process and presented Apache's Ant as an effective solution to the simplification of the process. In this week's article, we'll look at a complete example, including everything from the source code to the build artifacts within the Eclipse integrated development environment. This article assumes that the reader has a basic understanding of Eclipse and its Java projects.
Set Up Ant
Because we're focusing on using Ant from within Eclipse, the good news is that Ant is prepackaged as part of Eclipse's base installation image (be sure you're using Eclipse 3.2 or newer). This means there are no additional steps; your environment is ready for Ant! However, if you would like additional information about configuring the Ant runtime for use outside of Eclipse, there is a wealth of information available at the official Ant Web site.
Develop Source Code
Before we create an example build script, we need to create something to build. To demonstrate this process, let's create a simple HelloWorld Java program (shown below in Figure 1) in an Eclipse Java project named HelloWorld.
Figure 1: Here's a simple HelloWorld Java program.
The Build Script
Now that we've got our source code, we need to build its "distributable" form (e.g., a file named HelloWorld.jar). Herein lies the problem: How do we build our sample program in a simple, reliable, and repeatable fashion? This is where Ant saves the day.
build.xml
The first step in building our project with Ant is to create a build.xml file. Though the file doesn't need to be named build.xml, it must contain the .xml file extension (i.e., all Ant build files are merely XML files). A good practice is to place this build file in your project's root-level directory; in our case, that's the HelloWorld top-level directory.
Build File Structure
An Ant build file contains one or more targets. A target is effectively a named executable entity exposed to the user (e.g., compile might be the name of a target). It's common for a build file to consist of several targets wherein each target accomplishes one logical step within the overall build process. Build targets can also depend on one or more targets. That is, if a target depends on other targets, those targets will be implicitly executed when the target is run.
Although there's no enforcement of what your targets should be, in nearly all instances it's beneficial that your Ant build script contain at least these common targets:
- load: This target is responsible for loading the source code. Often, the source exists in a content management system, and most CMS providers offer Ant support (e.g., Ant provides CVS-related tasks out-of-the-box).
- preprocess: This target performs any preprocessing that needs to be done prior to compiling the source code (e.g., you might automatically increment your product's build number here).
- compile: This target compiles the source code, sending any generated class files to a classes artifacts directory.
- package: This target packages the compiled object code into a distributable entity (or entities); for example, you might create YourProduct.jar or YourProduct.war.
- javadoc: This target produces documentation for your application's source code.
- build: This target typically performs the entire build process, by either being dependent on all targets or simply being on the final target in a large dependency chain (e.g., imagine that A depends on B, which depends on C, etc. All would be performed via transitivity).
- clean: This target deletes any artifacts produced by the Ant build; often, this is a dependent target by other targets, ensuring that the build always starts afresh.
Of course this list is by no means comprehensive; most product builds entail a lot of steps, but even the most complicated build processes can be split into many smaller entities (i.e., targets). This set of tasks is intended as a means of pointing you in the right direction. In doing so, one isn't forced to perform the entire build, but rather only a subset.
An Example
Let's look at an example Ant build file (below) that will build our HelloWorld program (Figure 1).
<!-- An example Ant build script that will automatically create HelloWorld.jar for us. -->
<project name="HelloWorld" default="build">
<!-- Here we are defining a directory in which our build-related files will be placed,
relative to the special Ant property, basedir, which refers to the directory from which
Ant was launched. -->
<property name="build.dir" location="${basedir}/build" />
<!-- Defines the directory in which the source code will be placed. -->
<property name="src.dir" location="${build.dir}/src" />
<!-- Defines the directory in which the output (i.e., artifacts) of the build. -->
<property name="artifacts.dir" location="${build.dir}/artifacts" />
<!-- Defines the directory in which compiled code will be placed. -->
<property name="classes.dir" location="${artifacts.dir}/classes" />
<!-- Defines the directory in which distributable jars will be placed. -->
<property name="jars.dir" location="${artifacts.dir}/jars" />
<!-- The clean target is responsible for deleting old build artifacts and preparing for
a fresh build to occur. -->
<target name="clean">
<delete dir="${build.dir}" />
<mkdir dir="${build.dir}" />
<mkdir dir="${src.dir}" />
<mkdir dir="${artifacts.dir}" />
<mkdir dir="${classes.dir}" />
<mkdir dir="${jars.dir}" />
</target>
<!-- Defines the build target, which is dependent upon the jar target completing. -->
<target name="build" depends="package" />
<!-- Load our source code from our base directory. In most instances, you'd likely
retrieve your source code from your source control management system. -->
<target name="load" depends="clean">
<copy todir="${src.dir}" preservelastmodified="true">
<fileset dir="${basedir}">
<include name="**/*.java" />
</fileset>
</copy>
</target>
<!-- Perform any necessary pre-processing on the source code. In this case, we're
not going to do anything, but you might imagine incrementing a build revision, etc. -->
<target name="preprocess" depends="load" />
<!-- Compile our source code, directing generated .class files to the classes directory. -->
<target name="compile" depends="preprocess">
<javac srcdir="${src.dir}" destdir="${classes.dir}" />
</target>
<!-- Create our .jar file, which consists of all compiled .class files. -->
<target name="package" depends="compile">
<jar destfile="${jars.dir}/HelloWorld.jar">
<fileset dir="${classes.dir}">
<include name="**/*.class" />
</fileset>
</jar>
</target>
</project>
Running the Build Script
Eclipse provides out-of-the-box support for you to work with your Ant build files. To load the Ant view, click on Window > Show View > Other > Ant > Ant. You can then drag and drop any of your Ant build files into the Ant view (Figure 2). Once loaded, further expanding a particular Ant build will display its executable targets. Double-clicking a target will cause it to execute. This simplicity becomes especially beneficial when you need to perform several builds within a short period of time (e.g., during development).
Figure 2: This is the Ant view within Eclipse.
Using the Build Artifacts
Now that our build has successfully completed, we can navigate to the appropriate artifact directory and grab the build artifacts of interest (e.g., HelloWorld.jar, auto-generated Java documentation, etc.). These artifacts may then be distributed as needed; you may even create your Ant script such that it not only builds your projects, but also uploads your build artifacts to some well-known location (i.e., a common hub for distribution).
Go Build!
By now, you should have not only a solid understanding of why it's important to have a solid build infrastructure, but also a simple and effective tool to guide you along the way (hint, hint: Apache Ant). While this article by no means scratches the surface of all that Ant has to offer, it does make you aware of the basics and offer you some helpful suggestions to dig a little deeper. So go on; try building your next project with Ant.
LATEST COMMENTS
MC Press Online