I have just uploaded
javatools
0.5 to unstable and it is currently waiting in NEW.
Anyone wishing to try it out earlier can find source and packages (it's arch: all)
at
http://www.srcf.ucam.org/~mjj29/javatools/
.
Javatools replaces the existing
jarwrapper
package and also contains programs
to help packagers in creating packages for Java programs and libraries.
Packaging tools
The
javahelper
package consists of several small programs which make
packaging Java programs and libraries easier. They are generally designed to work
in the same fashion as the debhelper programs, but start with the
jh_
prefix.
All of the programs have their command line arguments documented in manpages.
jh_build
Many Java programs and libraries are distributed without sane build systems.
jh_build
provides a simple interface for building Java source code
into Jars, including setting the appropriate entries in the manifest.
In almost all cases all that needs to be done to call
jh_build
is to set
JAVA_HOME
and
CLASSPATH
and then call
jh_build
with the
name of the jar and the directory containing the source.
JAVA_HOME=/usr/lib/jvm/java-gcj
CLASSPATH=/usr/share/java/esd.jar:/usr/share/java/jsch.jar
jh_build weirdx.jar src
This command will compile all the Java files under
src
, set the
classpath in the manifest and build it all into weirdx.jar.
A couple of other options are worth mentioning. If this jar contains an application
rather than a library then the
-m
or
--main
option can be used
to set the
Main-Class
attribute in the manifest which will allow the resulting jar
file to be be executed
jh_build
also provides a
--clean
parameter which should be called in the
clean
target of
debian/rules
.
jh_libs
For library packages Debian Java policy currently requires that the libraries be installed
to
/usr/share/java
in a versioned format and with an unversioned symlink.
jh_libs
will take a jar and correctly install it.
As with debhelper programs, this can either take a jar as a parameter, or read a list of
jars from a file in the Debian directory. It also follows the
-p
,
-i
and
-s
semantics of debhelper for selecting which packages to install the jar to.
When operating on a package,
jh_libs
will read the list of library jars from
debian/package.jlibs
or
debian/jlibs
.
The jlibs file is a list of jars to install, one per line, and works exactly the same as listing
them on the command line. Each jar is installed to
debian/package/usr/share/java/
in
the appropriate versioned and unversioned forms.
jh_depends
jh_depends
works like dpkg-shlibdeps, but for jar files. For each jar in the package it
takes the jars on which it depends and finds the packages to which they belong. These are included
in the debhelper substvars as
$ java:Depends
. The control file can then just list that
variable which is filled in automatically.
This is done by reading the
Class-Path
attribute from the manifest of each jar. Jar files
should include this attribute to prevent applications which use them from needing a full recursive
classpath in their startup scripts and to prevent unneccessary transitions when the library changes
its dependencies. If the package is not built with
jh_build
and the upstream build system
doesn't set it correctly then
jh_manifest
can be used to fix this.
If the application uses executable jars (see
Runtime support
below) then jh_depends will
also add the appropriate depends on
jarwrapper
and the correct Java runtime.
jh_manifest
Many upstream build systems do not set the
Class-Path
attribute in the jars they create.
This leads to several unwanted problems, such as expanding the classpath which applications have
to use and introducing unneccessary transitions. They also may not set the
Main-Class
attribute. Both of these are required for running jars with the
-jar
parameter.
jh_manifest
can fix the manifest files of jars. It can either read from a manifest
file in the Debian directory or run in a mode which updates all the jars with the CLASSPATH
environment variable.
The manifest files can either be
debian/package.manifest
or
debian/manifest
.
The format of this file is a list of jars and indented below each one a list of manifest elements
to set:
usr/share/weirdx/weirdx.jar:
Main-Class: com.jcraft.weirdx.WeirdX
Debian-Java-Home: /usr/lib/jvm/java-gcj
jh_exec
The
Runtime support
section below describes running executable jars directly.
jh_exec
will scan package directories for jars in the paths, or symlinks to
jar from the paths, and ensure that they have been set executable if necessary.
jh_makepkg
jh_makepkg
will create template Debian packages for Java programs and libraries
similar to
dh-make
. It should be run in the source directory and it will
create the orig.tar.gz and most of the files in the Debian directory, which need only
small changes neccessary to build the package.
java-propose-classpath
Some upstreams have complicated classpaths which may not be obvious to the packager
when using
jh_manifest
to set the
Class-Path
attribute.
java-propose-classpath
will unpack a jar and look at the symbols imported to
the class files, then scan all the jars in
/usr/share/java
. This shouldn't be
run in the build since it is slow, and there may be ambiguities that the packager must
resolve. It is still very useful for the packager as most of the time it will get it right
automatically.
Runtime support
Javatools also provides some runtime support. Unlike compiled programs, or purely interpreted
programs with hash-bang lines, Java programs cannot be directly executed. Many upstreams
expect them to be run using
java -jar jarname
or
java classname
. This is not
generally acceptible in systems which expect to just be able to run the command or launch it from
a menu. As a result, many packagers are writing wrapper scripts which just call java with the correct
classpath, jar and main class.
jarwrapper
There is an alternative to wrapper scripts, however. The
binfmt_misc
kernel module allows
the kernel to call out to a program in userspace to execute specific types of file.
jarwrapper
registers itself as a handler for executable jars. This is done by reading values from the manifest
file.
In order for executable jars to work the following attributes must or may be defined in the manifest.
These attributes can be set using
jh_build
and
jh_manifest
.
- Main-Class: The name of the class to be run when the application starts. (REQUIRED)
- Class-Path: The path to all the jar files on which this jar depends. (REQUIRED unless empty)
- Debian-Java-Home: A Debian-specific property if this application depends on a specific runtime.
Specify the path to the runtime which should be used. (OPTIONAL)
- Debian-Java-Parameters: A Debian-specific property if this application needs extra options
to the JVM. (OPTIONAL)
Putting it together
This section shows the debian packaging generated by
jh_makepkg
for an application and a library
using
jh_build
.
Sample Library Packaging
debian/control
Source: jsch
Section: libs
Priority: optional
Maintainer: Matthew Johnson
Build-Depends: debhelper (>= 5), javahelper, java-gcj-compat-dev, libzlib-java
Standards-Version: 3.7.3
Homepage: http://www.jcraft.com/jsch/
Package: libjsch-java
Architecture: all
Depends: $ java:Depends , $ misc:Depends
Description: Java secure channel
JSch is a pure Java implementation of SSH2. JSch allows you to
connect to an sshd server and use port forwarding, X11 forwarding,
file transfer, etc., and you can integrate its functionality
into your own Java programs. JSch is licensed under a BSD style
license.
debian/rules
#!/usr/bin/make -f
export JAVA_HOME=/usr/lib/jvm/java-gcj
export CLASSPATH=/usr/share/java/zlib.jar
build: build-stamp
build-stamp:
dh_testdir
jh_build jsch.jar src
touch $@
clean:
dh_testdir
dh_testroot
jh_build --clean
dh_clean
rm -f build-stamp jsch.jar
install: build
dh_testdir
dh_testroot
dh_clean -k
dh_installdirs
binary-arch: build install
# Java packages are arch: all, nothing to do here
binary-indep: build install
# Create the package here
dh_testdir
dh_testroot
dh_clean -k
dh_install -i
dh_installdocs -i
dh_installchangelogs -i
dh_javadoc -i --sourcedir=src
jh_libs -i
jh_depends -i
dh_compress -i
dh_fixperms -i
dh_installdeb -i
dh_gencontrol -i
dh_md5sums -i
dh_builddeb -i
binary: binary-indep binary-arch
.PHONY: build clean binary-indep binary-arch binary install
debian/libjsch-java.jlibs
jsch.jar
Sample Application Packaging
debian/control
Source: salliere
Section: misc
Priority: optional
Maintainer: Matthew Johnson
Build-Depends: debhelper (>= 5), java-gcj-compat-dev, fastjar,
libmatthew-debug-java, libcsv-java,
libitext-java, javahelper
Standards-Version: 3.7.3
Package: salliere
Architecture: all
Depends: $ java:Depends , $ misc:Depends
Description: Short Description
Long Description
debian/rules
#!/usr/bin/make -f
export JAVA_HOME=/usr/lib/jvm/java-gcj
export CLASSPATH=/usr/share/java/csv.jar:/usr/share/java/debug-disable.jar:/usr/share/java/itext.jar
build: build-stamp
build-stamp:
dh_testdir
# Build the package
jh_build salliere.jar src
touch $@
clean:
dh_testdir
dh_testroot
jh_build --clean
dh_clean
rm -f build-stamp salliere.jar
install: build
dh_testdir
dh_testroot
dh_clean -k
dh_installdirs
binary-arch: build install
# Java packages are arch: all, nothing to do here
binary-indep: build install
# Create the package here
dh_testdir
dh_testroot
dh_clean -k
dh_install -i
dh_installdocs -i
dh_installchangelogs -i
jh_manifest -i
dh_link -i
jh_exec -i
jh_depends -i
dh_compress -i
dh_fixperms -i
dh_installdeb -i
dh_gencontrol -i
dh_md5sums -i
dh_builddeb -i
binary: binary-indep binary-arch
.PHONY: build clean binary-indep binary-arch binary install
debian/salliere.install
salliere.jar usr/share/salliere
debian/salliere.links
usr/share/salliere/salliere.jar usr/bin