<pack>
Ant Task
v1.7 (change history)
1. Purpose
<pack>
is a task which, given a set C of compiled Java™ classes, computes the support set for C - that is, the set of classes which the classes in C depend upon - and create a JAR containing all and only the classes needed to run C.
In other words, it builds the smallest JAR possible to link and run any given class.
From version 1.6, also automatic packing of entire packages is supported. Please see Notes on using packages instead of classes below.
Additional features comprise the definition of a Main-Class and a Class-Path for the JAR, plus the possibility of explicitly adding additional classes (and their support sets) and files.
Note: <pack>
analyzes classfiles to discover dependencies; it cannot, however, detect classes which are linked or loaded indirectly (via Class.forName or similar mechanism), as such classes can even be completely undetermined until runtime (imagine some code that obtains a class name from the user, and attempts to load the class via Class.forName).
However, if such classes are known when the packing occurs, the "additionalClass" subelement of <pack>
can be used to explicitly include them in the produced JAR while visually distinguishing them from the core packed classes.
Similarly, the "ignoreClass" elements can be used to explicitly ignore classes.
2. Defining the task in an Ant build script (typically build.xml)
As any external Ant task, <pack>
needs to be defined in your build script. <pack>
lives in the org.sadun.util.ant
package, which in turn is contained in the org.sadun.util.jar library, and its class name is Pack
. Therefore, add an entry
<taskdef name="pack" classname="org.sadun.util.ant.Pack" classpath="..pathname.../org.sadun.util.jar"/>in your
<project>
(where classpath is the path to the org.sadun.util.jar library) to be able to use <pack>
.
3. Task attributes and subelements
The following are attributes of the <pack>
element.
Attribute | Type | Description |
classes | (mandatory (*)) | A comma-separated list of classes to pack. |
packages | (mandatory (*)) | A comma-separated list of packages to pack. |
classpath | (optional) | Classpath to use when packing classes. A nested standard Ant < classpath > element can be also used (see Ant documentation for details).
The classpath is initialized according to the value of build.sysclasspath (which in turn is valued "first" by default, for backwards compatibility). |
targetJar | (mandatory) | The name of the jar file to produce. |
mainfestClassPath | (optional) | The manifest Class-Path entry. |
mainfestMainClass | (optional) | The manifest Main-Class entry. |
excludePkg | (optional) | A comma-separated list of package prefixes to exclude. Defaults to java,javax,sun. |
includePkg | (optional) | A comma-separated list of package prefixes to include. Only classes in matching packages will be included. Has lower precedence than excludePkg. |
resolveFiltered | (optional) | If true, allows resolution of classes which are filtered out. Defaults to false |
cacheClassFiles | (optional) | If false, disables classfile caching, which slows down the packing process but saves memory. Defaults to true |
(*) classes and packages are alternative.
The classes specified by classes and all the classes in their supporting set must be in Ant classpath or in the classpath specified by the optional classpath attribute. In other words, if your classes use some libraries, etc, they must be in classpath.
Subelement/attribute | Description | <resource> |
name=" resource name" | the name of the resource to add | <additionalclass> |
name=" classname" | the name of the additional class to add | <ignoreclass> |
name=" classname" | the name of the class to ignore |
<additionalfileset> | A standard Ant <fileset > element (see Ant documentation for details). |
<classpath> | A standard Ant <classpath > element (see Ant documentation for details). |
The classes defined by <additionalclass>
must
excludePkg
/includePkg
.
Resources names defined by
Notes on using packages instead of classes
The packages attribute is a fast way to avoid listing the entire contents of a package in the "classes" attribute or by using <additionalClass> subelements.
However, this leaves pack with the task of finding out which classes belong to which package. This information may actually vary for different JVMs settings or even for different runtimes with the same settings (depending for example on the used ClassLoaders, user-defined classpath, etc).
To do the job, the current version of pack employs a java package explorer object for that purpose, which scans the classpath indicated by the classpath attribute or classpath subelements. The current implementation of that object has certain limitations, in particular:
Therefore, be aware that using packages may lead to incorrect results in situations which do not fall within the limitations above.
<resource>
can be given both in zip path form (for example, my/package/MyResources.properties) or in java-package form (for example, my.package.MyResource.properties).
4. Examples
The following definition will create a runnable JAR with all the classes necessary for running my.test.pkg.Test which makes use of the my.library.jar library:
<pack classes="my.test.pkg.Test" classpath="my.library.jar" targetJar="my.library.jar" manifestMainClass="my.test.pkg.Test"/>
The following definition will create a runnable JAR as above, but adding the entire library to the JAR and adding the relative Class-Path entry to the Manifest. Only the classes whose fully qualified name is prefixed with my.test are included in the resulting jar:
<pack classes="my.test.pkg.Test" classpath="${basedir}/my.library.jar" targetJar="my.library.jar" manifestMainClass="my.test.pkg.Test" includePkg="my.test" manifestClassPath="./my.library.jar"> <additionalfileset dir="${basedir}"> <include name="my.library.jar"/> </additionalfileset> </pack>The following definition will also include explicitly the an.other.Class class and the resource an.other.Resource.properties:
<pack classes="my.test.pkg.Test" classpath="${basedir}/my.library.jar" targetJar="my.library.jar" includePkg="my.test" manifestMainClass="my.test.pkg.Test" manifestClassPath="./my.library.jar"> <additionalfileset dir="${basedir}"> <include name="my.library.jar"/> </additionalfileset> <additionalclass name="an.other.Class"/> <resource name="an.other.Resource.properties"/> </pack>
The following definition will create a runnable JAR with all the classes and necessary for linking the entire package my.test.pkg which makes use of the my.library.jar library (see also the notes above):
<pack packages="my.test.pkg" classpath="my.library.jar" targetJar="my.library.jar" manifestMainClass="my.test.pkg.Test"/>
5. Downloading
<pack>
is part of the package sadun-util whose source and binary form can be downloaded from sourceforge.