[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Library handling in squeeze + 1



One of the other things we discussed at DebConf 10 is the handling of Java
libraries. For the benefit of those not at DebConf here are the problems and
conclusions we reached (it's long, but there are some questions at the end).

Leaving aside the problem of detecting when upstream break ABI compatibility
without telling us (for which we also discussed this), there are a number of
problems around handling this which we don't currently answer.

 - if an ABI is added to and a package using the new ABI is built against it,
 the dependency can still be satisfied by an older package without that ABI.

 - if an ABI is changed incompatibly it can satisfy the dependency for a
 package which used the old ABI. 
	
 - We have no way of doing coordinated transitions - if a library changes, all
 it's r-depends must be immediately fixed.

The second (related) problem is to do with recursively loading classpaths:

 - If library A depends on library B, currently any application depending on A
 must include B in its classpath.

The solution for all this is to change our handling of libraries as follows:

 - Library packages must include the ABI version in the package name, so the
 source package will be called foo0, the binary package will be called
 libfoo0-java etc.

 - Libraries must install jars as $name-X.Y.Z.jar (package/upstream version)

 - Libraries must install a symlink $name-A.jar (where A is the ABI version)

 - Libraries must conditionally install a symlink $name.jar if they are the
 highest abi version installed on the system (this must be done in postinst, 
 so that multiple packages with different ABIs can be coinstalled)

 - ABI versions may be taken from part of the upstream version or may be
 assigned internally by Debian

 - Libraries must list all their non-optional dependencies in the Manifest
 classpath (this corresponds to packages which appear in Depends and do not
 appear in the Depends of the library's r-depends)

When building against a library you must:
	
 - build-depend on the package including the abi version (libfoo0-java)

 - use the symlink without a version in your build classpath unless you
 specifically want the older ABI version 

 - use the symlink with the ABI version but not the full upstream version
 in your runtime classpath

 - depend on the library package including the abi version with the dependency
 versionned to be >= the version built against or (if this can be calculated)
 an earlier version which is known to work

This will have the following effects:

 - multiple packages with different ABIs can be installed simultaneously in
 order to ease transitions, or support a release with both ABIs

 - rdepends of such packages will depend on and use the correct jar

 - packages will only have their depends satisfied by a version with a
 compatible ABI

 - programs don't need to recursively enumerate classpaths, just list their
 immediate dependencies

 - a library adding a dependency does not cause all its r-depends to transition

 - if a library only makes backwards-compatible changes everything will Just
 Work (tm)

 - if a library ABI changes in a backwards-incompatible change you must:

	- change the source and binary package names (requiring a trip through NEW),
	- build-r-depends which work with the new ABI just need the dependency
	updated to the new version, but no upstream source or build system changes,
	- build-r-depends which _don't_ work with the new version will obviously
	need fixing
	- rdepends will continue being installable and working with the old ABI
	until the transition is complete
	- when all rdepends have moved to the new ABI the old source package needs
	to be removed from the archive

In order to make this easier, a lot of it can be supported by tooling:

 - installation of the symlinks will be done by jh_installlibs (with the ABI
 version inferred from the package name)

 - the conditional symlinks will be handled by a prerm/postinst snippet which
 will be automatically generated by javahelper

 - references to foo.jar in manifest files will be rewritten to be foo-A.jar by
 jh_manifest

 - classpaths can be added to non-compliant jars with jh_classpath or
 jh_manifest

 - jh_depends will populate your Depends: list including minimum version
 numbers

 - javahelper will provide a method to do replacement of the classpath elements
 in wrapper scripts at build time so that they point to the correct symlink for
 that ABI.

I shall write the bits of these which are missing and start staging them via
experimental until squeeze is released. This will mean that essentially all
Java packages must use javahelper, but I think it's a good idea to do so
anyway.

There has also been some discussion of providing symbols files similar to C
libraries which could be used to detect unannounced ABI changes from upstream
and to relax the version in dependencies. Some work needs to be done to see how
feasible that is.

A question which just occurs to me is: should we encode the ABI in the jar
somehow? Possibly a manifest entry? Are there any other manifest entries we
should be adding?

Please follow up in case that I've missed anything here, or you have any
questions.

Matt

Attachment: signature.asc
Description: Digital signature


Reply to: