Gentoo Logo

Ant Guide

Content:

1.  Split-Ant

Since version 1.7.0, the way of packaging and using optional tasks in Apache Ant has changed substantionally. Previously, Ant was split into ant-core (the core .jar files) and ant-tasks (.jar files for all the optional tasks, most of which have quite a number of external package dependencies). Ant-tasks symlinked its jars into the ant-core/lib to be loaded. Dependencies of these optional tasks were hardcoded into the ant startup script and tried to be loaded even if they (or ant-tasks) were not installed. This way they would pollute the classpath for building and cause packages that also depend on some of these to build even without the dependencies recorded in ebuild and package.env.

With the new split-ant setup, each .jar file that made up ant-tasks package is installed as separate package (named ant-* as the jar file itself), specifying just the dep(s) it itself needs. The jars are not symlinked to ant-core/lib but instead, the presence of the package is recorded by touching a file named /usr/share/ant/tasks-${PV}/${PN}. Ant startup script is modified so that by default it looks into this directory and loads the tasks and their deps for backwards compatibility. But the real power lies in the ANT_TASKS variable (used in ebuild or by ant user) which can override this default behaviour and specify only the tasks you want it to load. To sum up, the advantages of new layout are:

  • Reduced dependencies of packages that need more than ant-core (instead of depending in whole ant-tasks with its almost 20 direct dependencies, you specify only those you want)
  • Less classpath pollution, no hardcoded dependencies inside ant startup script (see above)
  • Easy to find if you need more than ant-core to build a package (with old setup you would have to unmerge ant-tasks to test if package fails without them)
  • Allows us to have junit3 and junit4 in separate slots and choose which one to load in ant
  • Better controlled build of the jars, instead of a manifest-only jar it will fail if there's something wrong with the dependency package
  • Full backward compatibility with existing ebuilds

2.  End User Documentation

Migrating to Ant 1.7.0

To make the transition possible, dev-java/ant-core-1.7.0 needs to block on older versions of dev-java/ant-tasks and dev-java/ant. So when you encounter this block, just unmerge ant-tasks and ant, and reissue the emerge command that caused it. If you don't use Ant yourself, that's all you need to know.

Working with new setup

If you use ant for your own Java development, you should be aware of few things. If you use only the tasks provided by Ant, there will not be any difference if you install the whole dev-java/ant meta-package. But the external libraries that used to symlink their .jar files into /usr/share/ant-core/lib to be loaded, will soon stop creating these symlinks. In order to load these libraries, you will now need to use the new ANT_TASKS environment variable, which takes space-separated list of packages to load.

Example of ant invocation with pmd and checkstyle libraries: ANT_TASKS="pmd checkstyle" ant

You can also use this variable to load libraries that didn't previously symlink into ant-core/lib, without the need to pass the full path with the -lib /path/to/jar parameter.

3.  Ebuild Developer Guide

A developer writing ebuilds has to generally take care about two things - dependencies and ANT_TASKS variable. For dependencies, if you previously needed only dev-java/ant-core (which is added by java-ant-2 eclass automatically), nothing changes. But if your ebuild needed full dev-java/ant or dev-java/ant-tasks to compile, you should figure out which exact optional tasks are needed (more on that later) and specify them in DEPEND. Then, you need to list the tasks in ANT_TASKS variable before calling eant (can be different for each eant call). In the most simple case, the tasks you need don't depend on useflags, you don't care about specific versions and all eant() calls in your ebuild need the same set of tasks. Then you just list the tasks you need in WANT_ANT_TASKS variable *before* inheriting java-ant-2.eclass, and it will fill the DEPEND and ANT_TASKS for you. In the more complex cases, you have to specify all the depends yourself (maybe based on USE flags) and ANT_TASKS for each eant call (also maybe based on USE flags). Typically you do this with test flag and ant-junit.

Env variables to use and know how they work

  • ANT_TASKS - $IFS-separated list of optional tasks (ant-foo) or even external libraries ant can use (xjavac...) to load. Used by eant. You can't set this in ebuild global scope, use only inside src_compile() or src_test()
  • WANT_ANT_TASKS - like ANT_TASKS, but you specify this before inheriting java-ant-2 and it can contain only ant-* tasks. Will be translated into dev-java/ant-* in DEPEND and used as default ANT_TASKS if you don't set (override) it yourself.
  • EANT_ANT_TASKS - if you use the default src_compile() of java-pkg-2, and can't use WANT_ANT_TASKS for some reason, set this in the global scope to pass ANT_TASKS value to it.
  • JAVA_PKG_FORCE_ANT_TASKS - like ANT_TASKS, but you don't use this in ebuild, but in the env, overrides any ANT_TASKS and WANT_ANT_TASKS set in the ebuild (in eant, does not bring the deps, because of portage dep caching). Can be used to easily hash out which tasks you need when writing the ebuild, without need to alter it each time.

Here are the order of how eant() processes these variables to export the final ANT_TASKS for calling the ant script, from highest lowest priority of overriding.

  • JAVA_PKG_FORCE_ANT_TASKS (set in the environment)
  • ANT_TASKS (set in the src_* function calling eant())
  • EANT_ANT_TASKS (for java-pkg-2 default src_compile())
  • WANT_ANT_TASKS (set in the ebuild global scope before inherit)
  • "none" (the default)

Typical workflow

Usually you start with dev-java/ant-core as dependency ( added automatically with java-ant-2 eclass ) and see if you can compile the package. If it fails, see what class was missing and see the next section to determine what ant-* package you need to use. The failure looks like this:

Code Listing 3.1: Sample missing task error

[junitreport] java.lang.ClassNotFoundException?: org.apache.tools.ant.taskdefs.optional.TraXLiaison

Here you can see that the failing task was junitreport, and the class it was missing.

4.  Implementation details (dev-java/ant* maintainer notes)

Build system (build.xml) changes

All ant-* ebuild share the same source tarball. Upstream's build.xml is already building different .jar files based on the classes dependencies, and there are selectors for the right source files. But it's using <available> statements to determine if dependency is present on classpath, and if not, it builds a manifest-only jar (or no jar at all, there's now a property for that in 1.7). We modify the build.xml to have separate target for core jars and target for the optional jars, where a property tells it which jar we want (easier to add 20 target differing just in name). We also make sure that only the source we want in the jar is compiled, and used for resolving internal class dependencies. Rest of these dependencies (for the optional jars) is resolved from symlinked ant.jar from the ant-core already installed on system, and in some cases also from ant-nodeps.jar (ant-nodeps package). This makes sure that all internal dependencies are represented with DEPEND variable in the ebuild and package.env.

Launcher script changes

Ant's launcher script now recognizes ANT_TASKS environment variable. The value is IFS-separated list of packages (in our usual package-slot format as recognized by java-config -p) that are translated to list of jar files (using java-config) and passed to ant with -lib parameter. There are also special values "none" and "all" (the default if not defined at all or empty). If "none" is specified, the only jars loaded by ant are those in /usr/share/ant-core/lib. This means no optional tasks, since they no longer symlink to here. Value of "all" will make the script load all tasks registered in /usr/share/ant/tasks(-version). The value of list can specify any ant-* tasks that are part of the ant distro itself, but also any external packages providing ant tasks (xjavac, ant-owanttasks) or in fact any package that provides something ant tasks can use (rhino for script tasks...).

Eclasses

We added one new eclass - ant-tasks.eclass used by the ant-* packages. Makes use of the shared build system, so ebuilds themselves only have to define few specific things. Is pretty well commented, so no details needed here. Few other java eclasses were modified to make use of the new features in other ebuilds. This is mostly about handling the ANT_TASKS variable and its friends WANT_ANT_TASKS and JAVA_PKG_FORCE_ANT_TASKS - see the developer docs. All changes and additions here are also commented.



Print

Page updated January 18, 2008

Summary: This document provides information on using Apache Ant on Gentoo

Vlastimil Babka
Author

William L. Thomson Jr.
Editor

Donate to support our development efforts.

Copyright 2001-2014 Gentoo Foundation, Inc. Questions, Comments? Contact us.