Antlibs
Specifying custom tasks for Apache Ant 1.7
Kev Jackson
ViNetworks - Senior Software Developer
Contents
- Who am I?
- Introduction - Extending Ant
- Antlibs - What?
- Antlibs - How? (the BIG bit)
- Ant 1.7 - New Features
Contents, no extra info.
Who am I?
Kev Jackson
Ant Committer, Ant 1.7 Release Manager
Extending Ant - Patch the code
- Post a patch or feature request on Bugzilla
- and wait...
- ...wait...
- ...wait for a committer to have the time to review your patch.
- Even then, the patch may not be suitable :(
Ant is designed to be extensible. From its xml build files, to the API that encourages third party developers to write their own tasks. But what are the options for extending Ant as a developer? From the very beginning, it was always possible to contribute via patches...
Extending Ant - Hack your own
- Download latest version from SVN repo...
- ...download required third-party libraries (there are a lot)...
- ...get the code to compile...
- ...finally write your custom code.
- Difficult to merge in beneficial changes from the trunk of the repo - are you paid as a full-time Ant customizer?
- Highly Unlikely!
So instead you could get the source code and change it as needed...
Extending Ant - <macrodef>
<macrodef name="hello-world">
<sequential>
<echo message="hello, world"/>
<sequential>
</macrodef>
|
- Good for some problems, but...
- ...only works by combining tasks that are already available
Wait, what about the XML? This macrodef looks handy...
Extending Ant - <exec>
- Like 'make', just shell out and call external program to do the work, but...
- ...not cross platform
- ...path problems
- ...many caveats for each different OS!
So we'll go old skool then!
Extending Ant - <scriptdef>
<scriptdef name="scripttest" language="javascript">
<![CDATA[
project.log("Hello from script")
]]>
</scriptdef>
|
- Supports many languages
- Can write new functionality very quickly, but...
- ...great for one off scripts, not great for reusable code
- ...needs the correct script jars on the classpath
Extending Ant - Custom Tasks
- Great!
- ...Complete control over what we do
- ...in Java so no problems* with different OS
- ...problem solved! Or, not quite...
- Classpath problems: example JUnit Task (how long has this been around?)
- ...http://ant.apache.org/faq.html#delegating-classloader-1.6
- ...and people still have problems getting it to work
- Simple fix...place all third-party jars in $ANT_HOME/lib
Extending Ant - Antlibs
- Advantages over a custom task
- ...available automatically (if placed in $ANT_HOME/lib)
- ...in Java so no problems* with different OS
- ...can bundle a lot of functionality together in one 'library'
- ...separate from Ant core (unlike optional taskdefs)
- ...can be updated separately from Ant core (no longer have to wait for new Ant to take advantage of new features in an antlib)
Antlibs - What?
- Just a custom task
- ...placed in $ANT_HOME/lib
- or in user.home/.ant/lib (for centrally managed installation)
- or you can specify them manually
- ...with an antlib.xml file
- ...declared as part of an xml namespace in your build.xml file
Antlibs - Making a tla (GNU Arch) antlib
- Remember: just a 'normal' custom task
- 1: Install GNU Arch (tla)...
Antlibs - Making a tla (GNU Arch) antlib
Antlibs - Making a tla (GNU Arch) antlib
- 1: Install GNU Arch (tla)...
- 2: Write a command line wrapper similar to AbstractCVSTask...
Antlibs - Making a tla (GNU Arch) antlib
Environment env = new Environment();
Execute exe =
new Execute(getExecuteStreamHandler(), null);
exe.setAntRun(getProject());
exe.setCommandline(toExecute.getCommandline());
exe.setEnvironment(env.getVariables());
try {
String actualCommandLine =
executeToString(exe);
log(
actualCommandLine,
Project.MSG_VERBOSE
);
int retCode = exe.execute();
...
|
- See http://people.apache.org/~kevj/ant-tla/ant-tla.html for the full code
Antlibs - Making a tla (GNU Arch) antlib
- 1: Install GNU Arch (tla)...
- 2: Write a command line wrapper similar to AbstractCVSTask...
- 3: Add custom classes for individual actions (get/update etc)
Antlibs - Making a tla (GNU Arch) antlib
Antlibs - Making a tla (GNU Arch) antlib
Antlibs - Making a tla (GNU Arch) antlib
- 1: Install GNU Arch (tla)...
- 2: Write a command line wrapper similar to AbstractCVSTask...
- 3: Add custom classes for individual actions (get/update etc)
Antlibs - Making a tla (GNU Arch) antlib
<?xml version="1.0" encoding="utf-8"?>
<antlib>
<taskdef name="tla"
classname="org.apache.ant.tla.Tla"
/>
<taskdef name="registerarchive"
classname="org.apache.ant.tla.RegisterArchive"
/>
<taskdef name="get"
classname="org.apache.ant.tla.Get"
/>
<taskdef name="update"
classname="org.apache.ant.tla.Update"
/>
</antlib>
Antlibs - Making a tla (GNU Arch) antlib
- 1: Install GNU Arch (tla)...
- 2: Write a command line wrapper similar to AbstractCVSTask...
- 3: Add custom classes for individual actions (get/update etc)
- 4: Add an antlib.xml
- 5: Write a simple build file using the antlib...
Antlibs - Making a tla (GNU Arch) antlib
<?xml version="1.0" encoding="utf-8"?>
<project name="tla-test" basedir="../../../" default="get"
xmlns:tla="antlib:org.apache.ant.tla">
<property name="repo-dir" value="tla-test"/>
<target name="get">
<tla:registerarchive
repoURL="http://www.atai.org/archarchives/atai@atai.org--public/"
/>
<tla:get archive="atai@atai.org--public"
revision="tla--atai-dists--1.3.4"
dest="${repo-dir}" />
</target>
<target name="cleanup">
<delete dir="${repo-dir}"/>
</target>
</project>
Antlibs - Making a tla (GNU Arch) antlib
- 1: Install GNU Arch (tla)...
- 2: Write a command line wrapper similar to AbstractCVSTask...
- 3: Add custom classes for individual actions (get/update etc)
- 4: Add an antlib.xml
- 5: Write a simple build file using the antlib...
- 6: Test the code with the build file
Antlibs - Making a tla (GNU Arch) antlib
Antlibs - Making a tla (GNU Arch) antlib
- 1: Install GNU Arch (tla)...
- 2: Write a command line wrapper similar to AbstractCVSTask...
- 3: Add custom classes for individual actions (get/update etc)
- 4: Add an antlib.xml
- 5: Write a simple build file using the antlib...
- 6: Test the code with the build file
- 7: Write a repeatable test
Antlibs - Making a tla (GNU Arch) antlib
Antlibs - Making a tla (GNU Arch) antlib
Antlibs - Things to notice
- Not specified like a normal custom task
- Use xml namespaces
- Trivial to change a normal build file into an 'antunit' test
- What's this tla:register-archive?
- What about backwards compatibility with Ant 1.5 etc?
Antlibs - Build.xml -> Antunit test
- Add the antunit namespace to your build file
- Specify the driving target as the default in the build file
- In the driving target read in the build file (yes the same file), and set up the <au:plainlistener/>
- Write a target named 'testX'
- Inside 'testX', perform actions as normal
- After the actions have been performed use the appropriate <au:assertX/> to test the result
- For setup, add a <target name="setUp">
- For teardown, add a <target name="tearDown">
Antlibs - Antunit
- Antunit is an antlib
- Just like JUnit (setUp -> test1..testN -> tearDown)
- Dependencies are *still* called
- Antunit reads a buildfile (x.xml) to drive the tests
- Antunit provides basic assertions, but more can be added
- (My) preferred method of testing Ant task code (plain JUnit or even BuildFileTests are now obselete)
- Antunit, currently in Apache Ant Antlib SVN repo, should be released 'Real Soon Now' :)
- See http://ant.apache.org/antlibs/antunit/ for more information
Antlibs - tla:register-archive?
- Sorry, a required task so that we can 'get'
- Wanted to concentrate on one function for the examples
- In the code for this antlib, there are other features which I didn't reveal today...
- You can try the code out from http://people.apache.org/~kevj/ant-tla/ant-tla.html
Antlibs - A compatibility 'trick'
- What if you want to distribute a custom task that can run as both an antlib or as a normal custom task?
- DRY - Don't repeat yourself
- Create an antlib, and in the base directory write a properties file
- In the antlib.xml file, use <taskdef resource="tasks.properties"/>
- Example - Ant-contrib
Antlibs - A compatibility 'trick'
- Define tasks that are compatible with <Ant 1.6 in a properties file
Antlibs - A compatibility 'trick'
- Define tasks which require >Ant 1.6 in the antlib.xml
Antlibs - A compatibility 'trick'
- 1: DRY - Don't repeat yourself
- 2: Easier maintenance as edits can be made to the properties file and they are instantly available in the antlib
- 3: Good backwards compatibility for normal taskdefs, antlib tasks available for ant 1.6+
Antlibs - Inside antlib.xml
- Allowed inside an antlib.xml file:
- <taskdef>
- <typedef>
- <presetdef>
- <macrodef>
- <scriptdef>
- anything that implements the AntLibDefinition interface
- For Example, antunit:
Antlibs - Inside antlib.xml
Finally - Ant 1.7 new features
- ResourceCollections (can contain files, archives and URLs)
- Better Java5 support (eg <apt>)
- JUnit4 support in the <junit> task
- Full antlib support (hope to release svn antlib, antunit antlib, vss antlib at or around 1.7 release)
- <scp> task now supports sftp
- Better .Net support (including Mono)
- New <schemevalidate> task supports XSD files
- A lot of new conditions (issigned, scriptcondition, xor, parsersupports, typefound, isfailure, resourcesmatch, antversion)