[[!meta title="Multiarch Design"]] This is a [[release_goal|dev/releases/1/multiarch]] for release 1.0. There are three high-level design aspects to this multiarch implementation: the filesystem hierarchy that primarily enables package coinstallability, control information documenting package coinstallability and dependency satisfaction, and coinstallability considerations in package management. For reference, see the [specification][wuc-mas] and [other documentation][wdo-ma] for multiarch in Debian and Ubuntu. Filesystem Hierarchy ==================== For packages to be coninstallable with themselves (such that a user can have multiple architecture builds of one package installed simultaneously), all architecture-dependent files must be installed in architecture-dependent locations. The most straightforward way to do this is to embed architecture strings into filesystem paths. Debian and Ubuntu do something similar to this. In a Debian library package that supports multiarch, shared object files are installed in `/usr/lib/`, where `` is a [GNU system type][ac-systemtype]. The scope of Debian's and Ubuntu's multiarch work [does not include][wdo-ma-fut] coinstallable executable programs. Such work, however, would help enable cross installation of packages. So a goal of this multiarch implementation is to support coinstallation of shared object files, header files, and executable programs. There are two proposed filesystem hierarchies (see below) to support this. Parts of the toolchain (especially the dynamic linker) need to be configured and/or patched to use multiarch library paths. Additionally, at least the native-architecture executable program directories have to be added to the `PATH` environment variable (set in `libbb/messages.c` and `libbb/libbb.h` in the BusyBox source as of versions 1.19.3 and 1.20.2). Proposal 1: `/usr` Organized Primarily by Architecture ------------------------------------------------------ It may be useful to install all architecture-dependent files under `/usr/`, where `` is a distribution architecture string. The filesystem hierarchy would then look something like this: / +- bin/ | +- core-linux-eglibc/ | +- cortexa8-linux-eglibc/ | \- native -> core-linux-eglibc +- lib/ | +- core-linux-eglibc/ | \- cortexa8-linux-eglibc/ +- sbin/ | +- core-linux-eglibc/ | +- cortexa8-linux-eglibc/ | \- native -> core-linux-eglibc \- usr/ +- core-linux-eglibc/ | +- bin/ | +- games/ | +- include/ | +- lib/ | +- sbin/ +- cortexa8-linux-eglibc/ | +- bin/ | +- games/ | +- include/ | +- lib/ | +- sbin/ +- bin/ +- games/ +- include/ +- local/ +- native -> core-linux-eglibc +- sbin/ +- share/ \- src/ Note that `/usr/lib` doesn't exist, as no architecture-independent files should be installed there. BusyBox needs to be patched to set the `PATH` environment variable to `/sbin:/sbin/native:/usr/sbin:/usr/native/sbin:/bin:/bin/native:/usr/bin:/usr/native/bin`. Proposal 2: `/usr` Organized Secondarily by Architecture -------------------------------------------------------- It may be cleaner and slightly more efficient to install architecture-dependent files within an architecture-dependent directory under otherwise standard paths. This is similar to how Debian and Ubuntu have designed their multiarch filesystem hierarchy. Such an organized filesystem hierarchy would look something like this: / +- bin/ | +- core-linux-eglibc/ | +- cortexa8-linux-eglibc/ | \- native -> core-linux-eglibc +- lib/ | +- core-linux-eglibc/ | \- cortexa8-linux-eglibc/ +- sbin/ | +- core-linux-eglibc/ | +- cortexa8-linux-eglibc/ | \- native -> core-linux-eglibc \- usr/ +- bin/ | +- core-linux-eglibc/ | +- cortexa8-linux-eglibc/ | \- native -> core-linux-eglibc +- games/ | +- core-linux-eglibc/ | +- cortexa8-linux-eglibc/ | \- native -> core-linux-eglibc +- include/ | +- core-linux-eglibc/ | \- cortexa8-linux-eglibc/ +- lib/ | +- core-linux-eglibc/ | \- cortexa8-linux-eglibc/ +- local/ +- sbin/ | +- core-linux-eglibc/ | +- cortexa8-linux-eglibc/ | \- native -> core-linux-eglibc +- share/ \- src/ Note that this hierarchy is more consistent than is the hierarchy in proposal 1. That is, `/bin` and `/usr/bin`, for example, are both laid out the same. BusyBox needs to be patched to set the `PATH` environment variable to `/sbin:/sbin/native:/usr/sbin:/usr/sbin/native:/bin:/bin/native:/usr/bin:/usr/bin/native`. Control Information =================== New package control information will be needed to indicate whether a package is coinstallable with itself and to mark its purpose. During build-time, there are two possible architectures for any dependent package: * Host-architecture (architecture for which packages are built). Packages for this architecture provide things like libraries and headers. An example is `libexpat.1-dev`. * Build-architecture (architecture on which packages are built). Packages for this architecture provide things like build utilities. An example is `pkg-config`. During install-time, there are also two possible architectures for any dependent package: * Host-architecture (architecture for which packages are installed). Packages for this architecture provide things like libraries and utilities. Examples include `libz.1`, `gcc-4.7-` (dependency of `gcc-`), and `fakeroot` (recommendation of `opkhelper-1.0`). * Install-architecture (architecture on which packages are installed). Packages for this architecture provide things like utilities used by maintainer scripts. An example is `insserv` (or a similar tool). Host-architecture packages should be coinstallable with themselves, and they should satisfy dependencies of the same architecture. For example, the dependency of `libexpat.1-dev:cortexa8-linux-eglibc` on `libexpat.1` should resolve to a dependency on `libexpat.1:cortexa8-linux-eglibc`. Build- and install-architecture packages need not be coinstallable with themselves, and they should satisfy dependencies of any architecture. For example, the build dependency of `glib` (built on `core-linux-eglibc` for `cortexa8-linux-eglibc`) on `pkg-config` should resolve to a build dependency on `pkg-config:core-linux-eglibc`. Debian and Ubuntu specify such properties in a `Multi-Arch` control field. A value of `same` indicates that a package satisfies dependencies of the same architecture; a value of `foreign` indicates that a package satisfies dependencies of any architecture. We can implement something similar, perhaps even using the same terminology. Logic to handle the new control information will need to be added to opkg and opkhelper (specifically oh-checkbuilddeps). Special design considerations need to be given to install-time dependencies. Specific use case analysis can help here. Section-Based Solution ---------------------- A way to avoid having to modify opkg is to separate packages into archive sections by package type, e.g.: `bin`, `lib`, `dev`, `dbg`, and `share`. opkbuild could possibly automatically generate a correct `Section` control field by package name for many packages. prokit would add feed lists for the native-architecture `bin` and `lib` sections, and users would have to enable other feed lists themselves (e.g. to add a foreign architecture's `lib` and `dev` feeds to cross-build packages. Architecture-Independent Files ============================== Many packages provide architecture-independent files (configuration files, documentation, data, etc.). To the extent possible and feasible, these should simply be provided by architecture-independent packages (with names like `*-common`, `*-data`, or `*-base`). If this is not possible in all cases, then some modifications to opkg will be necessary (reference counting, implicit "Breaks" relationships, etc.). [wdo-ma]: http://wiki.debian.org/Multiarch [wuc-mas]: https://wiki.ubuntu.com/MultiarchSpec [ac-systemtype]: https://www.gnu.org/savannah-checkouts/gnu/autoconf/manual/autoconf-2.69/html_node/System-Type.html [wdo-ma-fut]: http://wiki.debian.org/Multiarch#Future_development