To kick-start the tour, let’s begin with a new feature that promotes consistency across projects. The <import> task lets you conveniently mix in tasks from other build files. Say, for example, you have a build file called build-common.xml that includes common properties and tasks, such as a compile target.
<project name="common">
...
<target name="compile" depends="prepare">
<javac srcdir="${src.dir}"
destdir="${build.prod.dir}"
classpathref="project.classpath"/>
</target>
...
</project>
Tomorrow you’re breaking ground on a new Java project, and it’s up to you to define the one-step build process. Obviously it will need to compile source files, so you need a compile target. Rather than falling prey to copy/paste reuse, create a project-specific build.xml file and import the existing build-common.xml file.
<project name="dms" basedir=".">
<import file="build-common.xml" />
</project>
By importing build-common.xml, the project-specific build file has inherited all the common tasks and properties. For example, you’ve barely broken a sweat typing angle brackets and you’re already compiling code:
$ ant compile
Buildfile: build.xml
prepare:
[mkdir] Created dir: /Users/mike/work/dms/build/prod
compile:
[javac] Compiling 4 source file to /Users/mike/work/dms/build/prod
BUILD SUCCESSFUL
Total time: 3 seconds
Ah, but your project needs to do some work before and after the compilation step. It’s tempting to copy the compile target and modify it for project-specific needs, but that’s only because you haven’t tasted another spice of <import>: target overriding. Simply override the compile target in your build.xml file to add more behavior.
<project name="dms" basedir=".">
<!-- Override common properties here. -->
<import file="build-common.xml" />
<target name="compile"
depends="pre-compile, common.compile, post-compile" />
<target name="pre-compile">
<echo>Compiling...</echo>
</target>
<target name="post-compile">
<echo>Done.</echo>
</target>
</project>
Notice that the project-specific compile target uses a dependency order to ensure that the local pre-compile target is invoked before the common compile target (specified as common.compile) and the local post-compile target is called at the end.
Now you have a project-specific compile step:
$ ant compile
Buildfile: build.xml
pre-compile:
[echo] Compiling...
prepare:
common.compile:
post-compile:
[echo] Done.
compile:
BUILD SUCCESSFUL
Total time: 3 seconds
Nothing was compiled because everything was up-to-date from the previous build, but notice that the common.compile target was indeed bracketed with your project-specific steps.
You’re done! So, now that your build process is in place, what’s next? Well, because setting up the build didn’t take long, you probably still remember that code you need to write. And now that you’re using the <import> task, hopefully you can steer clear of the build file until next week, when we peek at another new feature.