1.4. Anatomy of a Build File Ant projects all revolve around one or more build files. By default, Ant looks for a build file named build.xml. Because Ant files are XML documents, they start with an XML declaration, as all valid XML documents must: <?xml version="1.0" ?> . . . | For the complete XML 1.0 syntax, look at http://www.w3.org/TR/REC-xml/. XML 1.1 is out now as well, but Ant build files are based on XML 1.0, and the difference between these versions is small anyway, centering mostly on the manner in which certain Unicode characters are supported. |
|
1.4.1. Projects Every Ant build file contains exactly one project. You set up an Ant project in a build file with the project element, which is the document elementi.e., the element that contains all other elements: <?xml version="1.0" ?> <project> . . . </project> As Ant build files are just XML, you'll need to know which attributes are allowed on the top-level project element. | You'll also want to know about the elements that can be nested within project. Those are dealt with throughout the rest of this chapter and in Chapter 2. |
|
The three allowed attributes for the project element are shown in Table 1-1. Table 1-1. The project element's supported attributes Attribute | Description | Required |
---|
name | Defines the project name | No | default | The target to invoke if no target is explicitly specified | Yes | basedir | The base directory from which all relative paths are resolved | No |
Note that the default attribute is required. This attribute points to the Ant target that you want run by default; in other words, this controls what happens when you type ant at the command prompt, without any other special instructions. In the following case, the default target is main: <?xml version="1.0" ?> <project default="main"> . . . </project> 1.4.2. Targets An Ant target is a group of tasks that you want Ant to perform. These tasks are grouped together into one easily remembered unit, which is the target. For example, you might have a target deploy which opens an FTP connection to a remote server, uploads various files, and closes the connection. Though multiple tasks may be involved (opening the connection, performing an upload, closing the connection, and perhaps checking for error messages), it's easiest to think of this as one unit of work. Considering this as a single target makes it reusable and easily accessed from various portions of your build file. Another example might be a target named init that initializes a build by deleting output directories and recreating them so they'll be empty, as well as copying over license files that should be a part of every build. You might use a target named compile to compile dozens of source files across various directories and store the results in various output directories. In all these cases, the target handles piecing together various individual tasks. Ant build files are made up of targets like these. For example, to create the main target, you use the target element, along with the name attribute: <?xml version="1.0" ?> <project default="main"> <target name="main"> . . . </target> </project> You can see the possible attributes for the target element in Table 1-2. Table 1-2. The target element's attributes Attribute | Description | Required |
---|
name | Defines the target name | Yes | depends | Comma-separated list of targets to execute before this target | No | if | Name of a property needed to run this task | No | unless | Name of a property that can not be set before running this task | No | description | Description of this target's purpose | No |
1.4.3. Tasks You populate an Ant target with tasks; a task is an XML element that Ant can execute to make something happen. For example, the echo task echoes text messages to the console: <?xml version="1.0" ?> <project default="main"> <target name="main"> <echo> Building the .jar file. </echo> </target> </project> To create an Ant target, you place Ant tasks like echo inside a target element; in this case, the main target only has one task, but you can include hundreds. 1.4.3.1 Built-in tasks As you'd expect, Ant comes with a large number of built-in tasks, and you can see them all in Table 1-3 (many of these tasks may contain subelements). | In cases where a task is listed and followed by another task name in brackets (as in apply [execon]), the first task is the current name you should use; the second task is an older name that performs similar functionality but is now deprecated. Always use the task not in brackets to ensure your code is current. |
|
Table 1-3. Core Ant tasks Task name | Description |
---|
ant | Executes Ant | antcall | Executes a target from the current build file | antstructure | From a given build file, creates a DTD reflecting all of the tasks Ant currently knows about | apply [execon] | Invokes a native executable | available | Sets a Boolean value in a property according to the availability of desired resource | basename | Sets a property to the last element of a specified path in an effort to determine a file's name without directory structure | buildnumber | Manages build numbers | bunzip2 | Expands GZip or BZip2 archives | bzip2 | Packs GZip or BZip2 archives | checksum | Creates checksums for one or more files | chmod | Modifies file permissions on Unix | concat | Concatenates multiple files | condition | Checks the result of a condition and sets the result to in a property | copy [copydir, copyfile] | Copies files | cvs | Interacts with a CVS repository | cvschangelog | Converts a series of CVS change logs into an XML report | cvspass | Adds entries to a .cvspass file | cvstagdiff | Creates an XML report highlighting the differences between tags | cvsversion | Finds the CVS software version | defaultexcludes | Modifies the list of default exclude patterns, affecting which files are automatically excluded from processing by file-related tasks | delete [deltree] | Delete files and folders | dependset | Deletes target files that are older than new source files | dirname | Assigns a file's directory path to a property | ear | Extends the jar task to support handling files for an Enterprise Application archive (EAR) | echo | Echoes text to System.out or to a file | exec | Invokes a native executable | fail | Halts and exits a build by throwing a BuildException | filter | Sets a token filter that can be used by filter-related tasks such as copy | fixcrlf | Adds or remove tabs, carriage returns, linefeeds, and EOF characters from a set of files | genkey | Adds a new key to a given keystore | get | Retrieves files using FTP, HTTP, and more from a URL | gunzip | Unpacks a GZip file | gzip | Packs a GZip file | import | Allows the use of other Ant files | input | Displays a message and reads a line of input from the console, allowing for user input during the build process | jar | Creates a JAR archive similar to Java's jar command | java | Executes the Java interpreter to run a class or application | javac | Compiles the specified source file(s) | javadoc [javadoc2] | Invokes the javadoc tool to create documentation | loadfile | Sets a property file to the entire contents of a text file | loadproperties | Loans an entire property file into Ant properties | macrodef | Defines a new task as a macro built-up upon other tasks | mail | Sends SMTP mail messages | manifest | Creates an archive's manifest file | mkdir | Makes a new directory | move [rename] | Moves a file to another directory | parallel | Contains other Ant tasks that can be run simultaneously by multiple Java threads | patch | Uses the patch command (assuming it is on the path) to apply diff files to a source file (or files) | pathconvert | Converts paths between platforms | presetdef | Defines a new task based on an existing task with certain options preset as defaults | property | Sets one or more properties to new values | record | Runs a listener that records the logging output of the build process to a file | replace | Replaces a string with another in all files in a directory | rmic | Invokes the rmic compiler | sequential | A container task that can contain other Ant tasks and run them in sequence | signjar | Uses the JarSigner to securely sign ZIP and JAR archives | sleep | Suspends execution for a specified period of time | sql | Runs SQL statements against a database | subant | Runs Ant within all subdirectories of the project directory | sync | Synchronizes two directory trees | tar | Makes a new TAR archive | taskdef | Creates a new task definition and adds it to the current project | tempfile | Sets a temporary filename to an Ant property | tstamp | Sets time-based properties to the current time | typedef | Creates a new task or data type for use in the current project | unjar | Unpacks a JAR file | untar | Unpacks a TAR file | unwar | Unpacks a WAR file | unzip | Unpacks a ZIP file | uptodate | Sets a property value to true if a given target file is newer than a set of source files | waitfor | Halts a build and continues when specified conditions are met | war | Creates WAR archive files (an extension of the jar task) | whichresource | Locates a class or resource, either on the current class path or the system class path | xmlproperty | Loads Ant properties from an XML property file | xslt [style] | Transforms a set of documents via XSLT | zip | Creates and packs a new ZIP archive |
1.4.3.2 Optional tasks Besides these built-in tasks, called the core tasks, Ant supports many optional tasks, which you can see in Table 1-4. These tasks may require the support of additional JAR files, which you load into the Ant lib directory. For example, ftp uploads files to remote servers; you need to place the JAR files jakarta-oro.jar and commons-net.jar in your Ant lib directory to use the task. Another optional task is csc, which compiles Microsoft C# code: <csc optimize="true" debug="false" warnLevel="4" unsafe="false" targetType="exe" incremental="false" mainClass = "Main" destFile="app.exe" > <src dir="src" includes="*.cs" /> <reference file="${testCSC.dll}" /> <define name="RELEASE" /> </csc> | To determine which additional JAR files an optional task needs, see http://ant.apache.org/docs/manual/index.html#librarydependencies, which lists the needed libraries for each optional taskand where to get them. |
|
Table 1-4. Optional Ant tasks Task name | Description |
---|
antlr | Runs the ANTLR Translator Generator Language Tool. | attrib | Changes the permissions and/or attributes of a file. | cab | Creates CAB files (Microsoft archives). | chgrp | Changes file groups on Unix. | chown | Changes file ownership. | depend | Determines which class files are out-of-date compared to their source. | echoproperties | Lists the project's properties. | ftp | Supports a basic FTP client. | icontract | Generates a property file for iContract, an application for controlling assertions. | image | Performs bulk image manipulation. | jarlib-available | Checks for the presence of an extension. | jarlib-display | Displays the "Optional Package" and "Package Specification" information for JAR files. | jarlib-manifest | Generates a manifest with required dependencies. | jarlib-resolve | Searches for the location of a JAR file, setting the location to an ANT property. | javacc | Invokes the JavaCC compiler. | javah | Generates C header and source files for the Java Native Interface (JNI). | JPCoverage | Runs the JProbe coverage analyzer. | JcovMerge | Merges JProbe coverage snapshots. | JcovReport | Takes a JProbe coverage snapshot and creates a report. | jdepend | Uses the JDepend parser to generate code quality metrics. | jjdoc | Invokes the JJDoc documentation generator (used with JavaCC). | jjtree | Inserts parse tree building actions into source code using the JJTree preprocessor for the JavaCC compiler. | jlink | Deprecated. Merges archive contents. Use the zip and jar tasks with the zipfileset and zipgroupfileset attributes instead. | jprobe | Runs various tools from the JProbe suite. | jspc | Deprecated. Compiles JSP pages to Java source code. Use Tomcat's jspc task instead. | junit | Runs unit tests using JUnit. | junitreport | Merges separate XML files generated by the JUnit task into a single XML file. | maudit | Highlights stylistic and potential execution problems using the Metamata Metrics/WebGain Quality Analyzer. | mimemail | Deprecated. You can still send mail using the mail task. | mmetrics | Generates metrics using the WebGain's Metameta Metrics Quality Analyzer. | mparse | Takes a grammar file, and compiles it with MetaMata's MParse compiler. | native2ascii | Takes a native encoded file and converts it to ASCII. | netrexxc | Compiles all NetRexx source files. | propertyfile | Creates or modifies property files. | pvcs | Gets latest source code from a PVCS repository. | renameextensions | Deprecated. You can achieve the same results by using the move task and using a glob mapper. | replaceregexp | Replaces matched text with new text. | rexec | Controls a rexec session from Ant. | rpm | Builds Linux RPM installation files. | scp | Moves files to and from a remote SSH server. | script | Executes an Apache BSF script. | Scripdef | Defines Ant tasks from scripts. | serverdeploy | Runs a hot-deployment tool for a J2EE server. | setproxy | Configures web proxy properties. | sound | After a build, plays a sound file letting you know whether the build succeeded or failed. | splash | Displays a splash screen. | sshexec | Executes a command on a remote server using SSH. | stylebook | Uses Apache Stylebook to generate book documentation. | symlink | Makes, deletes, or edits Unix symbolic links. | telnet | Controls a Telnet session from ANT. | test | Executes a JUnit test. | translate | Translates keywords in files using values in resource bundles. | vajload | Loads files for Visual Age for Java source control. | vajexport | Exports packages for Visual Age for Java source control. | vajimport | Imports files for Visual age for Java source control. | wljspc | Compiles JSP pages using Weblogic's JSP compiler. | xmlvalidate | Validates XML files and reports any errors. |
In addition to these tasks, specific Ant tasks for .NET are shown in Table 1-5. Table 1-5. .NET Ant tasks Task name | Description |
---|
Csc | Invokes the C# compiler. | vbc | Invokes the VB.NET compiler. | jsharpc | Invokes the J# compiler. | ildasm | Disassembles from .NET intermediate language back to source code. | ilasm | Assembles code into .NET intermediate language. | WsdlToDotNet | Given a WSDL file, this task will generate C# or VB code. | ImportTypelib | COM library importer. |
Specific tasks for the Clearcase version control system are listed in Table 1-6. Table 1-6. Clearcase Ant tasks Task name | Description |
---|
CCCheckin | Checks in files. | CCCheckout | Checks out files. | CCUnCheckout | Un-checks out files. | CCUpdate | Executes cleartool update. | CCMklbType | Executes cleartool mklbtyle. | CCMklabel | Executes cleartool mklabel. | CCRmtype | Executes cleartool rmtype. | CCLock | Executes cleartool lock. | CCUnluck | Executes cleartool unlock. | CCMkbl | Executes cleartool mkbl. | CCMkattr | Executes cleartool mkattr. | CCMkdir | Executes cleartool mkdir. | CCMkelem | Executes cleartool mkelem. |
Many EJB specific tasks are shown in Table 1-7. Table 1-7. EJB-related Ant tasks Task name | Description |
---|
blgenclient | Generates a client JAR for Borland application servers. | ddcreator | Creates EJB deployment descriptors, given a group of WebLogic deployment descriptors. | ejbc | Invokes WebLogic's ejbc tool. | Iplanet-ejbc | Invokes iPlanet's ejbc tool. | ejbjar | Invokes the ejbjar tool (used for many application servers). | wlrun | Starts a WebLogic server. | Wlstop | Stops a WebLogic server. |
The Perforce source control tasks are shown in Table 1-8. Table 1-8. Perforce Ant tasks Task name | Description |
---|
P4Sync | Synchronizes files with the Perforce server. | P4Change | Gets a list of current changes from the Perforce server. | P4Edit | Checks out files for editing. | P4Submit | Checks in files. | P4Have | Lists all client-viewable files. | P4Label | Makes a label based on the files in the current workspace. | P4Labelsync | Syncs with a label. | P4Counter | Gets or sets a counter value. (Counters can be used to keep track of build events, such as the number of builds that have been executed.) | P4Reopen | Reopens a checked-out file. | P4Revert | Reverts file(s) that have been changed to their original content. | P4Add | Adds file(s) to the list to be submitted to the server. | P4Delete | Deletes file(s). | P4Integrate | Integrates file(s). You must specify the source file(s) and the target file(s). | P4resolve | Resolves file(s) in case others have made changes to the file(s) when you were working on it. | P4Fstat | Views differences with the server. |
Many tasks for Microsoft Visual Source Safe are detailed in Table 1-9. Table 1-9. Visual Source Safe tasks Task name | Description |
---|
vssget | Gets a copy of a particular VSS file. | Vsslabel | Makes a new label for the current version of a file. | Vsshistory | Displays a file's history in the project. | Vsscheckin | Checks in files to VSS. | Vsscheckout | Checks out files from VSS. | Vssadd | Adds a new file to VSS. | Vsscp | Changes the project considered the current project by VSS. | Vsscreate | Makes a new project. |
Continuing with source control repository tasks, Table 1-10 shows tasks for working with Starteam source control. Table 1-10. Starteam Ant tasks Task name | Description |
---|
STCheckout | Checks out files from StarTeam projects | STCheckin | Checks in files to StarTeam projects | STLabel | Creates a new label for this project | STList | Displays a list of files in the project |
Table 1-11 shows tasks for the Continuous source control server. Table 1-11. Continuous/Synergy Ant tasks Task name | Description |
---|
CCMCheckin | Checks in files to the source manager | CCMCheckout | Checks out files from the source manager | CCMCheckinTask | Checks in all files in the current task | CCMReconfigure | Reconfigures an existing command | CCMCreateTask | Creates a task |
Finally, Table 1-12 lists optional tasks for supporting SourceGear's SourceOffSite Visual Source Safe plug-in. Table 1-12. SourceOffSite Ant tasks Task name | Description |
---|
Sosget | Gets a read-only copy of a file | Soslabel | Creates a label for the current project | Soscheckin | Checks in files to the source manager | Soscheckout | Checks out files from the source manager |
In addition to the built-in and the optional tasks, Ant supports third-party and custom tasks (yes, that's a large number of tasks you can use!). As you'd expect, third-party tasks add functionality to Ant; as an example, take a look at the third-party tasks available for free at http://ant-contrib.sf.net/, which includes a set of tasks for use with Ant and C++. Creating Ant tasks is easier than you might think, and you're going to create your own in Chapter 11. 1.4.4. Dependent Tasks Typically, you create an Ant build file with a default target named something like main; this target then acts as a master target, handling program flow for the entire build process. It tells Ant to run other targets and specifies their ordering. This is accomplished through the target element's depends attribute. For example, you might want to add a target named compile to compile your code and add another target called compress to put the compiled code into a JAR file: <?xml version="1.0" ?> <project default="main"> <target name="main"> <echo> Building the .jar file. </echo> </target> <target name="compile"> <javac srcdir="."/> </target> <target name="compress"> <jar jarfile="Project.jar" basedir="." includes="*.class" /> </target> </project> Ensure that the compile and compress targets runin that orderby assigning the string "compile, compress" to the default target's depends attribute: <?xml version="1.0" ?> <project default="main"> <target name="main" depends="compile, compress"> <echo> Building the .jar file. </echo> </target> <target name="compile"> <javac srcdir="."/> </target> <target name="compress"> <jar jarfile="Project.jar" basedir="." includes="*.class" /> </target> </project> When you run Ant, it'll look for build.xml and execute the default target, which the project element indicates is main. The main target's depends attribute tells Ant to run the compile target and then run the compress target before running the body of the main target. | Though you use this attribute to indicate the order targets should run in, targets can still fail, which means you're not guaranteed that they will all behave as expected. Generally, a failed target will stop the Ant build process, but that's not always the case. |
|
Bear in mind that dependencies can be nested inadvertently. For example, take a look at this build file fragment: <target name="find"/> <target name="inspect" depends="find"/> <target name="test" depends="inspect"/> <target name="purchase" depends="test, inspect, find"/> If target purchase was the default target, you might think that targets test, inspect, find, and purchase were executed in that order. However, target test depends on target inspect, which depends on find, and so on. An Ant target gets executed once even when multiple targets depend on it. Because the dependencies of a task are executed before the task, the actual order of execution here is find, inspect, test, and then purchase. 1.4.5. Properties In addition to targets and tasks, the third pillar of an Ant build file is its properties. Properties are name-value pairs that act much like constants in Java code. You set the value of a property with the property element and can refer to that property by name throughout your build file. You can insert the value of a property in task attributes by dereferencing the property name with ${property-name}. For example, if you had a property named bin corresponding to the output directory of your build and wanted to refer to that directory, you could refer to it as ${bin} when you assign it to task attributes in your build file. If you wanted to refer to the archives subdirectory in that output directory, you could refer to it as ${bin}/archives. The advantages to this approach should be obvious to anyone who's had to change a directory name in 300 different places throughout an application. | A forward slash will work as a directory delimiter even on Windows systems; Ant is smart enough to know what you mean. |
|
1.4.5.1 Property attributes Properties are used the same way as constants are in Java: they let you collect definitions in one centralized place rather than having them dispersed throughout a build file. When you want to change property values, you can make changes in one location and know that they will propagate throughout the build file. You can see the attributes of the property element in Table 1-13. Table 1-13. The property element's attributes Attribute | Description | Required |
---|
classpath | The classpath to use when looking for a resource. | No | classpathref | The classpath to use when looking for a resource, which can then be given as a reference to a path element later in the build file. | No | environment | The prefix to use when retrieving environment variables. For example, if you specify environment="env", you will be able to access operating-system-specific environment variables as property names like ${env.PATH}. | A resource, file, url, or environment attribute is required when not using the name attribute. | file | The name of a property file to load values from. | A resource, file, url, or environment attribute is required when not using the name attribute. | location | Sets the property to the absolute filename of the given file. If an absolute path is supplied, it's left unchanged (with / and \ characters converted for the current platforms). Otherwise, the supplied filename is taken as a path relative to the project's base directory and then expanded. | A value, location, or refid element is required when using the name attribute. | name | The name of the property to set. | No | prefix | The prefix to add to properties loaded from a file or a resource. A . is appended to the prefix if none is specified. | No | refid | A reference to a (previously) defined object. | A value, location, or refid element is required when using the name attribute. | resource | The resource name of the property file, used for searching the classpath. | A resource, file, url, or environment attribute is required when not using the name attribute. | url | The URL from which to read properties. | A resource, file, url, or environment attribute is required when not using the name attribute. | value | The value of this property. | A value, location, or refid element is required when using the name attribute. |
As an example, you can store a message that displays "Building the .jar file." in a property named message: <?xml version="1.0" ?> <project default="main"> <property name="message" value="Building the .jar file." /> . . . </project> | You declare properties outside your targets. As of Ant 1.6, all tasks can be declared outside of targets (earlier versions only allowed property, typedef and taskdef to be used outside of a target element). When you define tasks external to a specific target, those tasks are evaluated before any targets are executed. |
|
You can echo the message to the console like this: <?xml version="1.0" ?> <project default="main"> <property name="message" value="Building the .jar file." /> . . . <target name="main" depends="compile, compress"> <echo> ${message} </echo> </target> </project> Properties are frequently used to hold pathnames, and the property element's location attribute is useful in this context. Suppose you're storing your source code in a subdirectory of the current directory named source and want to deploy the .jar file created by this build file to a directory named bin. You can create properties corresponding to these directories: <?xml version="1.0" ?> <project default="main"> <property name="message" value="Building the .jar file." /> <property name="src" location="source" /> <property name="output" location="bin" /> <target name="main" depends="init, compile, compress"> <echo> ${message} </echo> </target> . . . </project> The default target in this build file, main, depends on an init target where the mkdir task (detailed in Chapter 3) is used to create the output directory: <?xml version="1.0" ?> <project default="main"> <property name="message" value="Building the .jar file." /> <property name="src" location="source" /> <property name="output" location="bin" /> <target name="main" depends="init, compile, compress"> <echo> ${message} </echo> </target> <target name="init"> <mkdir dir="${output}" /> </target> . . . </project> Now you can compile the Java source code from the ${src} directory, placing the created .class file in the ${output} directory, and create the Project.jar file in the ${output} directory, all using properties: <?xml version="1.0" ?> <project default="main"> <property name="message" value="Building the .jar file." /> <property name="src" location="source" /> <property name="output" location="bin" /> <target name="main" depends="init, compile, compress"> <echo> ${message} </echo> </target> <target name="init"> <mkdir dir="${output}" /> </target> <target name="compile"> <javac srcdir="${src}" destdir="${output}" /> </target> <target name="compress"> <jar destfile="${output}/Project.jar" basedir="${output}" includes="*.class" /> </target> </project> The relative paths used will be expanded in a platform-specific way, something like this in Unix: -bash-2.05b$ ant -f properties.xml Buildfile: properties.xml init: [mkdir] Created dir: /home/steve/bin compile: [javac] Compiling 1 source file to /home/steve/bin compress: [jar] Building jar: /home/steve/bin/Project.jar main: [echo] [echo] Building the .jar file. [echo] BUILD SUCCESSFUL Total time: 2 seconds Here's the Windows version: C:\ant\ch01>ant -f properties.xml Buildfile: properties.xml init: [mkdir] Created dir: C:\ant\ch01\bin compile: [javac] Compiling 1 source file to C:\ant\ch01\bin compress: [jar] Building jar: C:\ant\ch01\bin\Project.jar main: [echo] [echo] Building the .jar file. [echo] BUILD SUCCESSFUL Total time: 4 seconds 1.4.5.2 Built-in properties Ant gives you access to the same system properties you'd have access to in Java code, as if they were Ant properties. For example, if you want to determine the name of the operating system, you can refer to ${os.name} in your build file. | For a list of system properties, see the Java documentation of the System.getProperties( ) method. |
|
Ant has some additional Ant-specific properties:
- ant.file
-
Contains the absolute path of the build file
- ant.java.version
-
Contains the JVM version Ant is using (can hold only 1.1, 1.2, 1.3, 1.4 and [as of Ant 1.6] 1.5)
- ant.project.name
-
Holds the name of the project that is executing (set with the name attribute of project)
- ant.version
-
Contains the version of Ant running
- basedir
-
Holds the absolute path of the project's base directory (set with the basedir attribute of project) |