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
signature.asc
Description: Digital signature