Using multiarch

To enable the installation of multiarch binaries, apt and dpkg need configuration changes. For example, if you have an amd64 system that you want to install i386 libraries onto, do the following:

Note that the command `dpkg --add-architecture` is not supported in Ubuntu 12.04 LTS and earlier

Converting your package for multiarch

This section is intended to be a one-stop guide for converting library packages to Multiarch. If you find there are issues not documented here, please update this wiki page, or contact debian-devel@lists.debian.org or #multiarch for help.

Information on build-dependencies and fixing non-library multiarch packages is on Multiarch/CrossDependencies.

Bug tagging: Tag new multiarch fixes with user=multiarch-devel@lists.alioth.debian.org, tag=multiarch usertags. Check existing bugs (to see if a package has already been fixed, or for examples): bugs tagged multiarch

Why update your library package for multiarch support?

Now that multiarch support is available in the package manager (dpkg 1.16.2 and above; apt 0.8.12 and above), converting your runtime library package to Multi-Arch: same makes it possible for users to install your package for more than one architecture at the same time. This has several benefits:

Issues to be aware of when converting

You might wonder why, if multiarch is so great, the conversion isn't handled automatically by the package helper tools like debhelper and cdbs. The answer is that there is no reliable way to automatically convert a package to multiarch. Careful attention is required on the part of the maintainer to ensure the conversion is done correctly. In particular, you must pay attention to the following issues:

What does the end result look like?

Currently, Debian Policy (9.1.1) provides for multiarch paths only for shared libraries. However, most upstream build systems (such as autoconf, with --libdir) will install shared libraries, support files, and various development files (such as static libraries and .so symlinks) together to the same target directory. It is intended that Debian Policy be amended to permit all of these files to be installed to the multiarch /usr/lib/<triplet> subdirectory.

With that fixed, the changes to packages for multiarch can be summarized as follows:

/usr/lib -> /usr/lib/<triplet>
/usr/lib/<pkgdir> -> /usr/lib/<triplet>/<pkgdir>
/usr/include: remains, used for arch-independent headers
/usr/include/<triplet>: used for arch-varying headers 
/usr/bin: no change
/usr/share: no change
/usr/sbin: no change

Packages that are Multi-Arch: same must adhere quite closely to Debian Policy section 8. In particular, since multiarch doesn't make any changes to the executable paths, a multiarch library package must not include binary executables in /usr/bin or /usr/sbin, since this will cause a conflict among the different architecture versions of a package. See Debian Policy: Shared library support files for advice on dealing with any such executables currently included in your runtime library package.

The end result, then, is a runtime library package that contains only files in the directories /lib/<triplet>, /usr/lib/<triplet>, /usr/share, and possibly /etc (though including configuration files in runtime library packages is generally discouraged). When these are all the files present in your runtime library package, your package can be marked Multi-Arch: same.

/!\ Note that any files in /usr/share or /etc must be byte-for-byte identical across architectures, otherwise file conflicts will result! This means, in particular, that any gzip-compressed files must be compressed with -n to avoid embedded timestamps.

Multi-Arch: foreign support packages

If your runtime library package follows Debian Policy section 8, there's a good chance that your library will have a dependency on some runtime support package such as libfoo-data. Since by definition the contents of this package are moved out of the runtime library package because they could be shared, you cannot install a copy of this package for each architecture and so it cannot be marked Multi-Arch: same. Instead, assuming that the interfaces the library uses to access these support files are architecture-independent, we instead mark this support package Multi-Arch: foreign to indicate that one copy of this package, of any architecture, is sufficient to satisfy the needs of the runtime library package of every architecture. No special dependencies or build-dependencies are needed in order to use Multi-Arch: foreign since this does not require multiarch-specific changes to the package's contents.

The Multi-Arch: foreign field must be set on such support packages regardless of whether they are Architecture: any, or Architecture: all. See the multiarch package manager spec for an explanation of this.

udeb handling

Although the runtime linker in the Debian installer environment is perfectly capable of finding libraries installed to the multiarch /usr/lib/arch path, it is unlikely that an installer will ever need to include binaries for more than one architecture; it is therefore recommended to install libraries directly to /usr/lib in udebs instead. Of course, plugins will need to be installed within a udeb to the directory where the binary will look for them; so if only the multiarch directory is on the search path, plugins will need to install to the multiarch directory even though the shared library may still be in /usr/lib.

Recipes for converting packages

dh(1) and autotools

The simplest package to convert is one that uses autoconf upstream and dh(1) in the Debian packaging.

  1. Build-depend on debhelper (>= 9).

  2. Update debian/compat to '9'.

  3. Replace occurrences of /usr/lib/ in debian/*.install with /usr/lib/*/.

  4. If /usr/lib (or a subdirectory) is listed as an installation target in debian/*.install, or the target of a link in debian/*.links, you will need to substitute the value of $(DEB_HOST_MULTIARCH) into this file. See Dynamic debian/* files below.

  5. Any occurrences of /usr/lib in debian/rules should be replaced with /usr/lib/$(DEB_HOST_MULTIARCH).

  6. If you needed to use $(DEB_HOST_MULTIARCH) in debian/rules in either of the two preceding steps, set DEB_HOST_MULTIARCH in debian/rules by calling: DEB_HOST_MULTIARCH ?= $(shell dpkg-architecture -qDEB_HOST_MULTIARCH) or simply including the external file: include /usr/share/dpkg/architecture.mk. This external Makefile is provided by package dpkg-dev.

  7. Once you have built the package and verified that the shared library package contains only the expected files, and that your -dev package still works, mark this shared library package Multi-Arch: same in debian/control.

  8. Mark the common package(which is "all") Multi-Arch: foreign in debian/control, if it may be needed by the shared library package.

If you have overridden debhelper commands in debian/rules, despite using dh(1) for the rest of the build, you may need to follow the instructions below for classic debhelper to modify mv, cp or rm commands used by your override rules.

cdbs with autotools and debhelper

Similar to short-form dh without need for specific debhelper compatibility level (dh_auto_configure not used) and less tight debhelper build-dependency (optionally none, see below).

  1. Build-depend on debhelper (>= 8.1.3) and on cdbs (>= 0.4.93~)

  2. Add DEB_CONFIGURE_EXTRA_FLAGS += --libdir=\$${prefix}/lib/$(DEB_HOST_MULTIARCH) to debian/rules.

  3. Replace occurrences of /usr/lib/ in debian/*.install with /usr/lib/*/.

  4. If /usr/lib (or a subdirectory) is listed as an installation target in debian/*.install, or the target of a link in debian/*.links, you will need to autogenerate this file to substitute in the value of $(DEB_HOST_MULTIARCH). See Dynamic debian/* files below.

  5. Any occurrences of /usr/lib in debian/rules should be replaced with /usr/lib/$(DEB_HOST_MULTIARCH).

  6. Once you have built the package and verified that the shared library package contains only the expected files, and that your -dev package still works, mark this shared library package Multi-Arch: same in debian/control.

  7. Mark the common package(which is "all") Multi-Arch: foreign in debian/control, if it may be needed by the shared library package.

To ease backporting you can additionally do this:

  1. Resolve /usr/lib/ install paths using $(DEB_HOST_MULTIARCH), either by autogenerating debian/*.install or by setting DEB_DH_INSTALL_ARGS_* (instead of statically setting /usr/lib/*/ in debian/*.install).

  2. Use debhelper compatility level 8 or lower.
  3. Build-depend unversioned on debhelper and cdbs (if your packaging do not need versioning for other reasons, obviously).

classic debhelper and autotools

If you call dh_* commands directly in debian/rules rather than using dh(1) or cdbs, these are the steps to follow when converting a library package for multiarch.

  1. Build-depend on debhelper (>= 8.1.3) in debian/control.

  2. Set DEB_HOST_MULTIARCH in debian/rules by calling: DEB_HOST_MULTIARCH ?= $(shell dpkg-architecture -qDEB_HOST_MULTIARCH)

  3. Add --libdir=\$${prefix}/lib/$(DEB_HOST_MULTIARCH) to each invocation of configure in debian/rules.

  4. Any occurrences of /usr/lib in debian/rules should be replaced with /usr/lib/$(DEB_HOST_MULTIARCH).

  5. Replace occurrences of /usr/lib/ in debian/*.install with /usr/lib/*/.

  6. If /usr/lib (or a subdirectory) is listed as an installation target in debian/*.install, or the target of a link in debian/*.links, you will need to autogenerate this file to substitute in the value of $(DEB_HOST_MULTIARCH). See Dynamic debian/* files below.

  7. Once you have built the package and verified that the shared library package contains only the expected files, and that your -dev package still works, mark this shared library package Multi-Arch: same in debian/control.

  8. Mark the common package(which is "all") Multi-Arch: foreign in debian/control, if it may be needed by the shared library package.

To ease backporting you can additionally do this:

  1. Set DEB_HOST_MULTIARCH in debian/rules by calling: DEB_HOST_MULTIARCH ?= $(shell dpkg-architecture -qDEB_HOST_MULTIARCH)

  2. Resolve /usr/lib/ install paths using $(DEB_HOST_MULTIARCH) by autogenerating debian/*.install (instead of statically setting /usr/lib/*/ in debian/*.install).

  3. Use debhelper compatility level 8 or lower.
  4. Build-depend unversioned on debhelper (if your packaging do not need versioning for other reasons, obviously).

autotools with no helper

  1. Build-depend on dpkg-dev (>= 1.16.0).

  2. Set DEB_HOST_MULTIARCH in debian/rules by calling: DEB_HOST_MULTIARCH ?= $(shell dpkg-architecture -qDEB_HOST_MULTIARCH)

  3. Add --libdir=\$${prefix}/lib/$(DEB_HOST_MULTIARCH) to each invocation of configure in debian/rules.

  4. Any occurrences of /usr/lib in debian/rules should be replaced with /usr/lib/$(DEB_HOST_MULTIARCH).

  5. Once you have built the package and verified that the shared library package contains only the expected files, and that your -dev package still works, mark this shared library package Multi-Arch: same in debian/control.

  6. Mark the common package(which is "all") Multi-Arch: foreign in debian/control, if it may be needed by the shared library package.

Dynamic debian/* files

For the common case, there should be no need to use dynamic debhelper config files, because a /usr/lib/* wildcard can be used instead to cover all possible directory names in an architecture-neutral manner. There are three main exceptions:

This last is particularly rare; note that dh_installdirs is only meant to be used when you need to ship an empty directory in a package, and not for creating directories that you will install files to. dh_install always auto-creates the parent directories that it needs for installing files.

It can be done with dh-exec or in the rules file.

CMake

The support for multiarch in cmake is provided via GNUInstallDirs module. Including it with

include(GNUInstallDirs)

does all sorts of checks and sets a few variables, most importantly CMAKE_INSTALL_LIBDIR (/usr/lib/<triplet>) and CMAKE_INSTALL_INCLUDEDIR (without the triplet part). The triplet value is taken from the CMAKE_LIBRARY_ARCHITECTURE variable which is autodetected on Debian systems (and depends on implicit library paths of the compiler set with CC or CXX variables).

Here are two examples how this is used to fix upstream cmake build: libdivsufsort and libsdsl. To properly support multiarch, you should convince your upstream authors to use GNUInstallDirs.

Note that include dir does not contain the triplet part. This may cause problems if your library has arch-specific header files. This is traced in bug 796545.

From debhelper 10.2.1 onwards CMAKE_INSTALL_LIBDIR is set by debhelper (to /usr/lib/<triplet>. This means that a fair number of packages (that install libraries to CMAKE_INSTALL_LIBDIR) will 'just work', so all you need to do is add:  depends: debhelper (>=10.2.1) 

There are a few other bugs discussing this issue, and the correct level of 'automation': 641051 722697

Qbs

Qbs does not have a built in 'libdir' concept, but it's easy to add such a variable, ensure it is used for libraries and symlinks, and set it in the rules file.

In the project.qbs file, define a library path variable:

Project {
  name: package
  property string LibDir: "lib"

Then use that variable in the project.qbs file to set the library and symlinks install path, e.g in the ?DynamicLibrary section:

  Group {
    fileTagsFilter: [ "dynamiclibrary", "dynamiclibrary_symlink" ]
    qbs.installDir: libDir
    qbs.install: true
  }

To use this, pass a multiarch setting for it in the debian/rules file (along with a /usr prefix):   qbs install --settings-dir /tmp --install-root $(PWD)/debian/tmp/ profile:deb modules.qbs.installPrefix usr/ project.libDir:lib/$(DEB_HOST_MULTIARCH)

Note that libDir does not include the '/usr' part, which is more correctly set as qbs.installPrefix. Put this in the .qbs project file:

More details of using Qbs in debian are available.

Other build systems

If you can provide a recipe for converting a package to multiarch when it uses something other than autotools as its build system, please add it here. If this build system is supported by dh(1), please also consider providing a patch to debhelper to automatically build for multiarch in compat level 9.

Historic information