The GNU binutils tools run on an "host" architecture and manipulate binary objects intended for later execution on a "target" architecture. Most combinations of supported Debian architectures are built from the binutils source package and extensively documented elsewhere.

This page collects informal suggestions and advices for packagers of the tools for less common "targets" with specific requirements. Usually, "host" is a desktop computer manipulating programs that will eventually be executed on an embedded "target" device with limited resources.

Scope

The following command should list packages with similar concerns.

   1 aptitude search '~n^binutils- !~n-dbg$ !~e^binutils$ !~v' -F%e | uniq

For a each result, the best source of information is usually "https://tracker.debian.org/pkg/PACKAGE".

Package names

For Debian architectures, the binary package is named binutils-TARGET_GNU_TYPE, with underscores replaced with dashes. New packages should follow this convention for consistency.

The source package should a priori have the same name.

Source package

Despite deriving from the same code base, the source packages for different targets should be separate Debian source packages. If a single source package were to produce binary packages for different targets, a release-critical bug affecting one target would get all targets removed from a Debian release. Maintainers of other targets are usually not in position to investigate because they do not own the specific hardware.

In order to share the upstream code, Debian patches and build system via the usual Build-Depends mechanism, the binutils source package distributes its own source in the binutils-source binary package.

If possible, the source package should be native (in the sense that debian/source/format should contain 3.0 (native)) and Build-Depend on binutils-source. This opion requires that the target keeps up with binutils development, and is always buildable using whatever the current version of binutils-source is.

If this assumption seems unrealistic, for example when the hardware vendor applies lots of patches and refreshes them unfrequently, a non-native package with an ad-hoc .orig tarball may be preferable.

Debian control file

Ideally, a paragraph of the long description should describe binutils generally and be identical in all similar binary packages, as this reduces the burden for translators.

No Multiarch qualification applies to the binary package.

Example of debian/control:

Source: binutils-YOUR-TARGET
Section: devel
Priority: optional
Maintainer: YOU
Build-Depends:
 binutils-source,
 bison,
 chrpath,
 debhelper-compat (= 13),
 flex,
 lsb-release,
 xz-utils,
 zlib1g-dev,
Rules-Requires-Root: no
Standards-Version: 4.5.1
Vcs-Git: https://salsa.debian.org/debian/binutils-YOUR-TARGET.git
Vcs-Browser: https://salsa.debian.org/debian/binutils-YOUR-TARGET

Package: binutils-YOUR-TARGET
Architecture: any
Depends: ${misc:Depends}, ${shlibs:Depends}, binutils-common
Suggests: binutils-doc
Built-Using: binutils (= ${binutils-version})
Description: GNU binary utilities for DESCRIBE-YOUR-TARGET
 This package provides GNU assembler, linker and binary utilities for
 a specific hardware and operating system combination.  You don’t need
 it unless you plan to cross-compile programs for it from another
 operating system.
 .
 This package targets DESCRIBE-YOUR-TARGET.

Binary package layout

Executable commands

Each TOOL (e.g. ld or strings) must be installed as /usr/bin/TARGET_GNU_TYPE-TOOL.

However, existing scripts often search the unprefixed name under the traditional usr/TARGET_GNU_TYPE/bin directory, so a symbolic link should make /usr/bin/TARGET_GNU_TYPE-TOOL available as /usr/TARGET_GNU_TYPE/bin/TOOL.

When the target is a full Debian architecture, the multiarch layout (/usr/lib/<multiarch triplet>/...) is used instead, but this is another story.

Dynamic linker scripts

should be installed in /usr/lib/TARGET_MULTIARCH/ldscripts/*.

Private libraries

The upstream system links the tools statically.

The Debian build system links tools dynamically with private libraries within the same package (namely, /usr/lib/HOST_MULTIARCH/lib{bfd,ctf}*TARGET*.so*).

For less common targets, the difference is small and the choice is mostly a matter of convenience.

Manual pages and translations

The manpage for TARGET_GNU_TYPE-TOOL may be identical to the one for TOOL in binutils-common.

The binary package may Depend on binutils-common and make /usr/share/man/man1/TOOL.1.gz available as a /usr/share/man/man1/TARGET_GNU_TYPE-TOOL.1.gz symbolic link.

The dependency must not require a specific version, else each upload of binutils would have to wait for all packagers of niche targets. Anyhow, this would not help much as the list of tools rarely changes.

The manual pages are small, so duplicating the contents is perfectly valid if more convenient.

Non-native packages must provide license information for the source version and patches they rely upon, and maintain a file largely redundant with the one from binutils-common.

Native packages must only describe the license of the packaging work, but must add a "Built-Using" dependency in debian/control, so that the Debian archive keeps the exact sources available alongside the executable as required by the binutils license.

Message translations

If the package already Depends on binutils-common for manual pages, the tools will display internationalized messages.

Else, the package may Recommend binutils-common and insert a paragraph like

Localized messages require the additionnal binutils-common package.

to the long description. Ideally, the paragraph should be identical for all targets so that itself requires only one translation.

In both cases, no version restriction should apply. Users of cross-compilers are expected to fear uninstallable toolchains more than untranslated messages.

Tests

The upstream test suite is quite long and mostly target-independant, so you may decide to skip it.

It is also possible to test a full compilation using the existing other elements of the toolchain. For targets with QEMU and bare-metal picolibc support (currently ARM, AARCH64 and RISC-V), it should be reasonably easy to adapt the test suite used at PicolispActions. Another example may be found in binutils-arm-none-eabi, whichs runs the compiler examples (though during continuous integration).

Continuous integration tests should be restricted to simple tasks involving only binutils. An upload of binutils triggers CI tests for all recursive reverse dependencies, so there is not much point in duplicating the libc(s) or compiler(s) CI tests.

Example of debian/tests/control:

Tests: basic
Restrictions: superficial

Example of debian/tests/basic:

   1 #!/bin/sh
   2 set -C -e -f -u
   3 
   4 cd "$AUTOPKGTEST_TMP"
   5 
   6 gnu_type=YOUR_TARGET
   7 
   8 touch foo.S
   9 $gnu_type-as foo.S
  10 $gnu_type-nm a.out
  11 $gnu_type-strings a.out

Stuff specific to the native scenario

Package version

A natural number should be sufficient as source package version (in debian/changelog), but the version of the binary package (set by {dpkg-,dh_}gencontrol) should change when a rebuild involves a new binutils-source version.

The binary version should join the binutils source version and the source version with a + (- would suggest a non-native package).

Source extraction

The directory extracted from the binutils tarball must be recreated during each build, in case the tarball has been updated.

This currently requires a build-dependency on xz-utils.

This invalidates the usual motivations for a versioned directory name or a separate build trees, so debian/rules may be simplified a bit.

In the following, the directory is arbitrary named src/.

It should also contain a copy of /src/binutils/debian/.

Patches

If patches are necessary, they must be stored outside the src/ throwable directory.

Please forward new patches as soon as possible, either to the upstream maintainers or via a Debian bug against binutils. Keeping a patch queue up-to-date for a single target is hopeless in the long run.

The debian/patches path is ignored by dpkg for native packages, but silents a lintian warning about a build-dependency on quilt without patches, and is probably more compatible with existing settings like QUILT_PATCHES.

It is convenient to export QUILT_PATCHES=../debian/patches, so that quilt considers src/ as the top source directory and writes patches that can be forwarded unchanged.

These commands should be added after extraction:

   1 cd src
   2 export QUILT_PATCHES=../debian/patches
   3 quilt push -a

When refreshing patches, please use `-pab --no-timestamps --no-index --sort` for normalized and less noisy patches.

Build dependencies

The list may vary depending on the target, but it at least contains

Build

The stamps/configure.ARCH generic recipes in src/debian/rules will do all the work. ARCH is expected to be a Debian architecture alias, from which the GNU type and multiarch path component are deduced. For a single target without existing Debian alias or i*86 substring, it should be safe to force all three to the same value.

Example of debian/rules:

   1 #!/usr/bin/make -f
   2 
   3 # https://wiki.debian.org/PackagingLessCommonBinutilsTargets
   4 
   5 include /usr/share/dpkg/pkg-info.mk
   6 
   7 export DEB_BUILD_MAINT_OPTIONS := hardening=+all
   8 
   9 gnu_type                                 = YOUR_TARGET
  10 arch                                     = $(gnu_type)
  11 multiarch                                = $(gnu_type)
  12 package                                  = binutils-$(subst _,-,$(gnu_type))
  13 
  14 %:
  15         dh $@
  16 
  17 execute_before_dh_autoreconf: src
  18 src:
  19         tar -xf /usr/src/binutils/binutils-*.tar.xz
  20         mv binutils* src
  21         cp -dr /usr/src/binutils/debian src
  22 
  23 override_dh_auto_configure: | src
  24         $(MAKE) -Csrc -fdebian/rules stamps/configure.$(arch) \
  25           _gnu_type='$(gnu_type)' _multiarch='$(multiarch)'
  26 
  27 override_dh_auto_build:
  28         $(MAKE) -Csrc -fdebian/rules stamps/build.$(arch) \
  29           _gnu_type='$(gnu_type)' _multiarch='$(multiarch)' \
  30           with_check=no
  31 
  32 override_dh_auto_install:
  33         $(MAKE) -Csrc -fdebian/rules stamps/install.$(arch) \
  34           _gnu_type='$(gnu_type)' _multiarch='$(multiarch)' \
  35           with_strip=no
  36 
  37 override_dh_install:
  38         dh_install --sourcedir=src/debian/$(package) -X/usr/include .
  39 
  40 override_dh_gencontrol:
  41         vsn=`dpkg-query -Wf'$${source:Version}' binutils-source` && \
  42         dh_gencontrol -- -v$$vsn+$(DEB_VERSION) -Vbinutils-version=$$vsn
  43 
  44 override_dh_clean:
  45         dh_clean src/

On the configure command line, you may want to set CONFARGS_TARGET with additional options for upstream configure script.

The with_strip=no option keeps the debug information for dh_strip.

The -X/usr/include option prevents a lintian warning about the directory being empty.

Lintian overrides

Example of debian/lintian-overrides:

# Traditional location of cross compiler tools.
non-standard-dir-in-usr usr/*/
file-in-unusual-dir usr/*/bin/*

# These private libraries are named after the target architecture,
# and only used by executables from this package.
package-name-doesnt-match-sonames lib*
exit-in-shared-library usr/lib/*/lib*
no-symbols-control-file usr/lib/*/lib*