Max Did It
Coding
,Tue
Post the First Comment
Tagged ,

How To Tidy Up Your Ant build.xml Files

Before I worked at Bigpoint, I built and published my Flash projects the naive way: Just press the right Button in the IDE, and then copy the result from the respective folder. As I learned there, using build scripts like Ant has many advantages over that method though. You can automatize many tasks like

  • deleting unnecessary files from previous builds,
  • copying assets to the target folder or
  • automatically providing libraries your project depends on.

What Annoyed Me About Ant So Far

Now, what bothered me a little bit about the way I used Ant was:

  • When I started a new project that I wanted to build with Ant, one of the first steps for me was: Open another, already working build.xml and copy all the stuff that already works and that I need. Which can be annoying and also means that you will have a lot of duplicate XML markup across a lot of different files.

  • Also, I have made the experience that build.xml files in bigger, complex projects using many different features can become very convoluted and confusing. Once your Ant build script spreads over several screens it can easily give you headaches.

What If I Told You...
Well, I dug a little through Ant’s documentation (RTFM). What if I told you that you can make your project specific build.xml only a couple of lines long?

The Include Tag

I have just set up a new SWC library project, and the build.xml in it’s entirety is this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<?xml version="1.0"?>
<project name="linkedlist" default="build" basedir=".">
	<!-- Properties -->
	<property name="library-path" location="lib/" />
	<property name="artifact-name" value="linked-list" />
	<property name="package-path" value="/de/maxdidit/linkedlist" />
	<property name="version" value="0.0.1" />
	<property name="target-dir" location="target/" />
	<property name="report-dir" location="report/" />
 
	<property name="commons" location="../../Commons" />
 
	<!-- Includes -->
	<include file="${commons}/Ant/build-as3-library.xml" />
	<include file="${commons}/Ant/ivy-targets.xml" />
	<include file="${commons}/Ant/flexunit-targets.xml" />
 
	<!-- Targets -->
	<target name="build"
		depends="build-as3-library.clear-target, ivy-targets.clear-dependencies, ivy-targets.retrieve, build-as3-library.compile-swc, flexunit-targets.test, ivy-targets.publish" />
</project>
</project>

This build script will resolve the dependencies of the project, build me a SWC file, run the unit tests and also publish the resulting artifact to my local Ivy repository (more about Unit Tests in my next posts. Find my post about Ivy here).

The trick is, of course, the include tag which takes other Ant build scripts and inserts their content in the current file. It’s little things like this that can make a big difference.

This allows me to create a handful of central scripts that contain tasks and targets that are used often. These need to be maintained only in one place and you can include their functionality with only one line of markup instead of copying whole building blocks into your XML files.

Outsourcing Ant Targets

All the task definitions and targets that would take up most of the space in an Ant build.xml file can now be put into separate files.

Let’s take a look at one of the build scripts I’m including up there. In the build-as3-library.xml file, I encapsulate everything I need for actually building a SWC library.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
<?xml version="1.0"?>
<project name="build-as3-library" default="compile-swc" basedir=".">
	<description>
This build file contains the properties and tasks you would usually need to build a Actionscript 3 SWC File.
	</description>
 
	<!-- environment variables -->
	<property environment="env" />
 
	<!-- Path to Flex SDK Home -->
	<property name="FLEX_HOME" location="${env.TOOLS}\flexsdk\flex-sdk-4.6" />
 
	<!-- Define Flex Ant Tasks -->
	<path id="flexTasks-path">
		<fileset dir="${FLEX_HOME}\ant\lib" includes="*.jar" />
	</path>
	<taskdef resource="flexTasks.tasks" classpathref="flexTasks-path" />
 
	<!-- Properties -->
	<property name="source-path" location="${basedir}/src/main/flash/" />
 
	<!-- Targets -->
	<target name="clear-target">
		<!-- Check if expected properties are set in the including file -->
		<fail unless="target-dir" />
		<!-- Delete contents of target directory -->
		<delete includeemptydirs="true" failonerror="false">
			<fileset dir="${target-dir}" includes="**/*" />
		</delete>
	</target>
 
	<target name="compile-swc">
		<!-- Check if expected properties are set in the including file -->
		<fail unless="target-dir" />
		<fail unless="source-path" />
		<fail unless="library-path" />
		<fail unless="artifact-name" />
		<fail unless="package-path" />
		<fail unless="version" />
		<!-- Build SWC library -->
		<compc output="${target-dir}/${artifact-name}-${version}.swc" >
			<source-path path-element="${source-path}" />
			<include-sources dir="${source-path}/${package-path}" includes="*.as" />
			<external-library-path dir="${library-path}" append="true">
				<include name="**/*"/>
			</external-library-path>
		</compc>
	</target>
</project>

I put all the necessary mark up into this file, like the tag which adds the Flex Ant tasks to the build script or the target containing itself. I don’t have to worry about any of these things in the actual build script that uses these targets. I can now use this script and include it in any library project that I will start in the future.

Take note of the properties that the targets use, like target-dir or library-name, but that aren’t defined anywhere in the build-as3-library.xml file. That is no problem, it’s okay if these are defined in the file that includes this script. I only test whether the properties the target requires have been set at one point of the build process with the fail tag.

Also be aware that all targets of a file you include get the name of the included project as prefix. In the build.xml, I can’t just call the compile-swc target from the included XML, I have to call build-as3-library.compile-swc.

Leave A Comment

Your email address will not be published. Required fields are marked *

Connect with Facebook

*

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>