Differences between revisions 25 and 26
Revision 25 as of 2011-03-22 06:28:50
Size: 13711
Editor: ?SteveLangasek
Comment: mention the .la references issue
Revision 26 as of 2011-03-22 13:44:44
Size: 13947
Editor: NeilWilliams
Comment: add warning for those who override bits of dh(1)
Deletions are marked like this. Additions are marked like this.
Line 60: Line 60:
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 class debhelper to modify mv, cp or rm commands used by your override rules.

/!\ WARNING: this page is a work in progress documenting a feature that is not yet available in the Debian archive and evolving rapidly. Do not rely on any information you read here when creating official Debian packages!

Converting your package for multiarch

This page 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 for help.

Why update your library package for multiarch support?

Now that multiarch support is available in the package manager (dpkg 1.16.0 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:

  • If your library is currently bundled in ia32-libs, providing a multiarch package helps with the process of removing ia32-libs from the archive.

  • If there is any software that uses your library which can only build in 32-bit mode, users will be able to install packages of that software directly on 64-bit systems without having to use dedicated chroots.
  • Users can use your library package with userspace emulators such as qemu without needing to use a dedicated chroot - making it easier to build environments that emulate only the parts that need emulating.

  • Although Debian policy currently doesn't allow -dev packages to be Multi-Arch: same, users may set up cross-build environments using only -dev packages for the target arch. Having your runtime library package built as Multi-Arch: same makes it easier to build software against your library in such an environment.

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:

  • To ensure that a multiarch-compatible libc is configured before your shared library package is unpacked to the new multiarch library paths (and the old version of the library deleted from /usr/lib), each shared library must declare a Pre-Depends on the multiarch-support package.

  • Any references to files located in /usr/lib from within your packaging, including but not limited to debian/rules, any debian/*.install or debian/*.links files, or maintainer scripts, must be updated by hand for the new locations.

  • If your library includes any sort of mechanism for loading modules or plugins from a public directory, care must be taken to ensure backwards-compatibility - either by including both multiarch and non-multiarch directories in a plugin search path, or by declaring an appropriate Breaks: on all pre-multiarch versions of the affected packages.

  • Test your -dev packages! There are several ways that a -dev package might be broken by a conversion to multiarch even though the runtime package works; pkgconfig .pc files may have wrong paths, .so symlinks may point to the wrong place, architecture-specific header files may become unavailable. Please check that the reverse-build-depends of your package still work after conversion.

  • Even if your -dev package isn't broken, if you ship a libtool .la file, the reverse-dependencies of your -dev package may have their own .la files with embedded references to the full path of your .la file; so when your .la file moves, the reverse-dependencies will break. It's for reasons like this that Debian Policy 10.2 recommends emptying the dependency_libs field of any .la files that you ship in a Debian package. A sample makefile rule to do this emptying at package build time can be found in /usr/share/gnome-pkg-tools/1/rules/clean-la.mk from the gnome-pkg-tools package.

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: no change
/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 cannot 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.

Recipes for converting packages

dh(1) and autotools

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

  1. Build-depend on debhelper (>= 8.1.3) (on Ubuntu: debhelper (>= 8.1.2ubuntu2).

  2. Add Pre-Depends: ${misc:Pre-Depends}  to any package listed in debian/control that provides a shared library.

  3. Update debian/compat to '9'. Note: debhelper compat level 9 is still under development; please pay attention to the section on Debhelper compatibility levels in the debhelper(7) manpage for information on other changes that may affect your package.

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

  5. If /usr/lib (or a subdirectory) is listed as an installation target in debian/*.install, or the target of a link in debian/*.link, you will need to autogenerate this file in debian/rules with an override target (and add the generated files to debian/clean so they're removed again in the clean target), to substitute in the value of $(DEB_HOST_MULTIARCH).

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

  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.

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 class debhelper to modify mv, cp or rm commands used by your override rules.

cdbs and autotools

CDBS doesn't have the equivalent of debian/compat to control its behavior, so a little more effort is needed if you use CDBS rather than dh(1).

  1. Build-depend on debhelper (>= 8.1.3) (on Ubuntu: debhelper (>= 8.1.2ubuntu2) and cdbs (>= 0.4.93) (on Ubuntu: cdbs (>= 0.4.90ubuntu9))

  2. Add Pre-Depends: ${misc:Pre-Depends}  to any package listed in debian/control that provides a shared library.

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

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

  5. If /usr/lib (or a subdirectory) is listed as an installation target in debian/*.install, or the target of a link in debian/*.link, you will need to autogenerate this file in debian/rules with a common-install-arch:: target (and clean up the generated file in the clean target), to substitute in the value of $(DEB_HOST_MULTIARCH).

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

  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.

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) (on Ubuntu: debhelper (>= 8.1.2ubuntu2).

  2. Add Pre-Depends: ${misc:Pre-Depends}  to any package listed in debian/control that provides a shared library.

  3. set DEB_HOST_MULTIARCH in debian/rules by calling:

    DEB_HOST_MULTIARCH ?= $(shell dpkg-architecture -qDEB_HOST_MULTIARCH)
  4. Add --libdir=\$${prefix}/lib/$(DEB_HOST_MULTIARCH) to each invocation of configure in debian/rules.

  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/*.link, you will need to autogenerate this file in debian/rules at the beginning of any install target, to substitute in the value of $(DEB_HOST_MULTIARCH). (If you do not have an install: target, you will need to do this at the beginning of your binary/binary-indep/binary-arch target.) You should then also clean up the generated file in the clean target.

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

  8. 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.

autotools with no helper

  1. Build-depend on dpkg-dev (>= 1.16.0) (on Ubuntu: dpkg-dev (>= 1.16.0~ubuntu4).

  2. Add Pre-Depends: multiarch-support to any package listed in debian/control that provides a shared library.

  3. set DEB_HOST_MULTIARCH in debian/rules by calling:

    DEB_HOST_MULTIARCH ?= $(shell dpkg-architecture -qDEB_HOST_MULTIARCH)
  4. Add --libdir=\$${prefix}/lib/$(DEB_HOST_MULTIARCH) to each invocation of configure in debian/rules.

  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.

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.