[This document is a slight clarification of amd64-multiarch-3.txt by ajt] How to handle multiarch on x86-64 (and other platforms). Problem and delimitations: We want to be able to install libfoo built for i386 and libfoo built for amd64 at the same time. The reason we want this is that we want to be able to install both applications linking against the 32 bit libraries and applications linking against the 64 bit libraries. This is only one case: We might want to install O32, N32 and N64 libraries on mips, or install i386, hppa and ia64 libraries on ia64. We are not trying to solve the issue of having the same application with different ABIs installed at the same time, so having both a i386 and an amd64 perl installed at the same time is out of scope for this document. Solution: We currently have the following constraints: * all packages installed on a system must be of the same architecture * only one package of a given name can be installed on any given system * dependencies are resolved by looking at package name and version only * packages that share files must not be concurrently installable * library packages share the same name across most architectures In order to achieve our aim, we need to relax the first constraint, and at least one of the others. If we choose to relax the last constraint -- that is, require libraries to have different names on different architectures -- we can avoid changing any of the other constraints. To that effect, we move libraries to /usr/$(gcc -dumpmachine)/lib and architecture-dependent include file to /usr/$(gcc -dumpmachine)/include. The support for /usr/$(gcc -dumpmachine) is already in gcc, so few changes should be needed there, and switching from compiling for, say amd64 to i386 would be accomplished through Linux personalities. The new constraints we require then are: * all packages installed on a system must be one of a set up supported architectures, determined by the systems cross-arch compatability. eg [amd64, i386], [ia64, i386], [s390, s390x], [powerpc64, powerpc, i386]. The latter case might require both hardware support (for ppc binaries) and software support (for i386 binaries). * packages that provide different functionality across architectures must be given different names (eg, libfoo-i386, libfoo-amd64, libfoo-powerpc) For library packages, we want the library itself to be multiply installable (so that apps of boths ABIs can link to the same library), and we want the development stuff to be multiply installable (why the hell not?). This leads to package names: lib- - the library (/usr//libfoo.so.a.b.c) - the soname link (/usr//libfoo.so.N) - libfooN-x, libfooM-x, libfooN-y must all be concurrently installable lib-dev- - the .a file (/usr//libfoo.a) - the .so symlink (/usr//libfoo.so pointing to /usr//libfoo.so.N) - arch-dependent include files - Provides: lib-dev - Depends: lib- lib-dev-common - arch: all - manpages, arch-independent include files - Depends: lib-dev lib-common - misc other stuff - libfooN-common must satisfy dependencies of libfooM-arch, for N >= M, wherever possible For i686 packages (which are compatible with i386 packages, but only work on i686 machines) the package name should remain libfooN-i386. The arch string (or, in general, package name) changes when a _different_ ABI is provided. For packages that provide a single ABI across all architecutres, eg, sed.deb, the package name does not need to be changed. For packages that do (most commonly libraries), it does. For libraries, dependencies can be automatically dealt with by adjusting shlibs. Scripting languages (python, perl, etc) tend to provide two ABIs: one for users (#!/usr/bin/python) which is arch independent, and one for modules (python2.3-foo, libfoo-perl) which is arch dependent. This means that all the installed modules have to match the installed interpretor, but that packages that use the modules don't need to care which one they use. Two names are thus needed for the interpretor, "python" for apps, and "python-i386" for modules: Package: python2.3 Architecture: i386 Provides: python2.3-i386 Package: python2.3-gnome2 Architecture: i386 Depends: libc6-i386 (>= 2.3.1-1), [...], python2.3-i386 Package: pybliographer Architecture: all Depends: python2.3, python2.3-gnome2, [...] Tradeoffs: Amongst others, the following tradeoffs can be made: * In the case where you set dpkg to allow you to install arch:i386 .debs on amd64 _today_, either: allow things to break (by allowing dpkg to satisfy foo(amd64)'s dependency on libbar by installing libbar(i386)); _or_ don't allow things to break (by interpreting all dependencies as requiring a .deb from the same arch), until new debs are uploaded * In the second case above, you can choose to require either: the deb doing the depending to be updated (foo Depends: bar:any); _or_ the deb being depended on to be updated (bar ABIConstantAcrossArches: yes) Questions: Q: But renaming packages doesn't scale! A: Does too. As long as the package name and version describes the ABI you're offering (and more particularly, depending on), there aren't any other problems. Q: How will dependencies be handled? A: Exactly as they are now. Q: What changes are needed? A: dpkg needs to be able to be told which non-native architectures it should install, and to not error out. Packages that don't offer the same ABI across architectures need to have their names changed. Q: What about /usr/lib64, /usr/lib and /usr/include? Q: What about /usr/X11R6? A: See Tollef's comments at http://raw.no/debian/amd64-multiarch-2 Q: Will this mean libfoo won't include a copyright file or changelog? A: It certainly will! /usr/share/doc/libfoo-i386/copyright, etc. Q: Isn't changing all those package names hard and disruptive. A: Yes. It can be made easier by letting you specify "${ARCH}" in debian/control and having dpkg-dev automatically rename the package appropriately. On the upside, the disruption is limited to renaming packages, which is something we're already familiar with: we don't need to change dependency resolution algorithms, we don't need to worry about having multiple packages with the same name installed at the same time, and we keep our mechanism for dealing with these problems (package names and versions) simple and general. --- How about adding an "ABI:" field? 1: What is an "ABI:" field? It's a field for handling ABI transitions without breaking dependencies, that should only be present during transitions. The idea is you start off with something like Package: foo Depends: libbar1, libc6 Package: libbar1 Depends: libc6 and switch to: Package: foo Depends: libbar1, libc6.1 ABI: libc6.1 Package: libbar1 Depends: libc6.1 ABI: libc6.1 The "ABI" field should be added to foo automatically when it gets built. It shouldn't be added (too) automatically to libbar1. The idea is we don't really want to have to change package names too often, especially for packages that can't be installed/distributed concurrently. Maybe it'd be better to say: Package: foo Depends: libbar1 [libc6.1] (>= 10), libc6.1 Package: libbar1 Depends: libc6.1 ABI: libc6.1 Yeah, that would be better. Hrm. The question is can something like that be used to make the transition between libfoo1 to libfoo1-i386. I can't see how that could be done without hacking up the architecture field to affect deps one way or another. Basically you want "Depends: libfoo1 (>= blah)" to be satisfied by "libfoo1-i386 >= blah" but only for some libfoo1, and only when their architectures match.