As Apache Ant is applied to increasingly difficult tasks, its users are creating more complex and less legible build files. This is due, in part, to the limited tools for decomposition and code reuse within previous versions of Ant.
The AntCall and Ant tasks can be used to help manage complex build files, but they have a high overhead cost and are not always legible. Without stronger features designed for decomposition and code reuse, it's difficult to manage the increasing length and complexity of Ant build files, and attempts to do so can obscure rather than clarify intent.
Fortunately, Apache Ant version 1.6 has several features that can help you manage the complexity of your builds and make the files more natural, legible, and faster. In particular, Macro Definition, Preset Definition, and Importation are powerful tools that can help reduce complexity.
Macro Definition When generalizing functionality in Ant, we have historically been faced with a set of options, each flawed. You can duplicate the code (copy and paste), which creates maintenance issues and other problems. Alternatively, you can use the Ant and AntCall tasks, which allow you to run Ant targets in a parameterized way. Finally, you can create a custom Ant task, which is extremely flexible but time-consuming and complicated, when the desired functionality already exists as a set of Ant tags.
Macro definition in Ant 1.6 offers to change all that by allowing the Ant user to create flexible macros that can be invoked within the Ant file without incurring the development overhead of a custom Ant task or the runtime overhead of an AntCall invocation.
If we compare the code in Listings 1 and 2, we can see that although the macro is a little less compact in this simple example, it's much more legible and will significantly reduce the overhead of code reuse by avoiding the reloading associated with an AntCall.
Macros seem even more powerful when you consider the ability to parameterize your macro with entire blocks of new code using the element tag, as shown in Listing 3.
Preset Definition Preset definition is a simpler, lighter, more compact form of a macro definition - the ability to customize existing tasks for your own purposes; it allows you to set default values or configuration settings for an existing task under a new name.
For instance, if you chose a more advanced logging structure for your build file, you might find it convenient to have an echo task customized to write a warning to your log file, as demonstrated in the following code:
1 <presetdef name="warn"> 2 <echo file="build.log" level="warning" /> 3 </presetdef> 4 5 <warn>Cannot locate configuration file: local.properties</warn>
By allowing you to customize and rename the task, Ant gives you the power to reuse common functionality and make the build files even easier to understand. These are important elements as everyday use of Ant becomes increasingly complex.
Listing 4 demonstrates how you might invoke a series of SQL statements in Ant 1.5.
By way of comparison, Listing 5 demonstrates the marked improvements made by using Ant 1.6's preset definitions.
This is already a vast improvement. The preset definition is slightly more complex, but the overall legibility is markedly improved, and there is far less duplication. Further, the Import Task, discussed in the next section, could allow you to move the preset definition to another file that defines presets and macros.
Import Task Ant 1.6 comes with an import task for composing one build file from component pieces. Although it was already possible to do some of this using XML entity includes, the import task is in a lot of ways more powerful and less arcane.
In a lot of cases the import task will be used simply, such as:
<import file="project-macros.xml" />
It does have more complex uses, however. The new import task allows you to override Ant targets in an almost polymorphic manner. Imagine you had this simple build file as shown below:
1 <project name="SuperClass" default="hello"> 2 <target name="hello" depends="sponsor"> 3 <echo message="Hello, World!" /> 4 </target> 5 <target name="sponsor" /> An 'abstract' target --> 6 </project>
If you wished to make use of this previously developed functionality, you could use the new import task to override or alter the functionality in a way that would be very familiar to object-oriented developers. This is demonstrated in Listing 6.
As Ant build files grow and evolve, these kinds of capabilities will give Ant the power of composition, to keep modules of Ant code simple enough to understand while allowing increased overall complexity.
XML NamespacesWhile macro definition and preset definition allow you to make better use of existing Ant functionality, there are times when you will want to add entirely new functionality to Ant by either developing a custom task or making use of third-party tasks.
Because all Ant tasks and types have operated in a common name-space, there has always been the potential for conflict between Ant tasks libraries, causing unnecessary integration issues. The following code demonstrates how Apache Ant 1.6 reduces this through the use of XML namespaces, allowing two similarly named tasks to coexist simply by allowing each library the use of its own namespace through the new URI attribute of the typedef task.
1 <project name="NS-No-Conflict" xmlns:ingenura="http://alpha.org" xmlns:beta="http://beta.org"> 2 <typedef resource="org/alpha/tasks.properties" uri="http://alpha.org" /> 3 <typedef resource="org/beta/tasks.properties" uri="http://beta.org" /> 4 <alpha:task /> 5 <beta:task /> <!-- same task name --> 6 </project>
With the use of the new Antlib task, libraries can be bundled in such a way that they are imported automatically when the namespace is defined using the antlib-structured URI, as shown below:
1 <project name="NS-Antlib" xmlns:ingenura="antlib:com.ingenura.tasks"> 2 <ingenura:task> 3 See how easy this is? 4 </ingenura:task> 5 </project>
Looking ForwardAnt is being applied to increasingly difficult tasks that call for increasingly complicated build files. Ant 1.6 provides several new and better ways to manage this complexity, making Ant files faster and more powerful, compact, and legible.
If you've been using Apache Ant, you'll appreciate many of the new features of Ant 1.6 that make it easy to use and enhance its power. If you haven't, perhaps this is a good time to take another look at Ant and what it can do for you.
Additional ResourcesFor more information, consider the following resources:
More information about the new features, including those found in the article as well as XML namespaces, Antlib, SSH, SCP, SubAnt and DefaultExcludes, can be found at http://nagoya.apache.org/wiki/apachewiki.cgi?NewAntFeaturesInDetail.
Specific information about new and existing tasks can be found in the Ant Manual at http://ant.apache.org/manual/.
For general information about Ant, see the Apache Ant Web site at http://ant.apache.org.
|