Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Packaging helpers and tools

Overview

The Rust team uses a very uniform way of packaging Rust crates, supported by various tools. The full pipeline for simple library or bin crates published on crates.io looks like this:

  1. debcargo-conf monorepo on salsa tracking all package crates
  2. debcargo used to translate upstream crate to Debian source package
  3. dh-cargo used by generated debian/rules file to drive building of source package
  4. cargo wrapper used by dh-cargo to ensure cargo behaves properly for package build purposes
  5. dh-cargo-built-using used by dh-cargo to analyze build artefacts and emit Built-Using and Static-Built-Using information
  6. cargo-auto-test used by generated debian/tests/control to run upstream test suite via autopkgtest

debcargo-conf

See Packaging a single crate for details.

debcargo

debcargo is a Debian packaging specific tool for converting a single upstream crate into a Debian source package.

debcargo package <crate> <version> consumes the following input:

  • upstream Cargo.toml file (metadata, dependencies, features)
  • debcargo.toml config file
  • an overlay directory containing a partial debian/ directory

to generate the full corresponding Debian source package.

Currently, the following files are automatically generated:

  • debian/control, including translated Build-Depends and Depends
  • debian/rules using dh-cargo
  • debian/copyright.hint skeleton for filling in the real debian/copyright
  • debian/tests/control using cargo-auto-test

By adding files to the overlay directory, it is possible to add additional parts which are copied verbatim to the generated source package. For files which would be generated by debcargo itself, the generated file will be suffixed with .hint, to allow easy diffing.

The debcargo package ships a fully commented version of debcargo.toml in /usr/share/doc/debcargo/debcargo.toml.example

By default, debcargo will fetch upstream sources from crates.io, but it is possible to point it a local directory instead by specifying crate_src_path in debcargo.toml.

debcargo currently only supports packaging a single crate! For more complicated packaging scenarios, refer to packaging processes.

dh-cargo

Small glue wrapper between debcargo-generated debian/rules and debhelper.

It currently hooks into the following parts of the package build:

  • dh_auto_configure: calls the cargo wrapper's prepare-debian command to setup cargo in a Debian package build context
  • dh_auto_test: calls either cargo build or cargo test, to verify the included Rust source actually builds
  • dh_auto_install
    • for library crates: copies the patched Rust source code into the "library" package
    • for binary crates: calls cargo install and dh-cargo-built-using to build the executables and collect information about what gets linked into them

dh-cargo currently only supports packaging a single crate, and only supports library or binary crates (or a combination of both)! For more complicated packaging scnearios, refer to packaging processes.

cargo-auto-test

cargo-auto-test is a wrapper around cargo test for usage in autopkgtests. It will use the cargo wrapper described below to ensure the tests are run against packaged test dependencies. debian/tests/control files generated by debcargo might serve as a good example for how to call cargo-auto-test manually, if desired.

cargo-auto-test only tests packaged library crates. For other test scenarios, directly calling cargo test via the cargo wrapper should work as well.

cargo wrapper

The cargo wrapper in /usr/share/cargo/bin/cargo is a small(ish) python script injected between the build driver (debian/rules, meson, pybuild, make, ..) and the real cargo.

It requires a few pieces of setup in debian/rules, see the top of the script itself and the example in complex packages for details:

  • source dpkg and rustc makefile snippets
  • depending on the build system, prepend /usr/share/cargo/bin to $PATH, or set $CARGO to /usr/share/cargo/bin/cargo
  • export some environment variables

As part of the auto_configure step of the package build, call the wrapper's prepare-debian command to generate a cargo config file and a fake cargo registry for vendored and/or packaged crates. This step is required for the wrapper to do its job, and should ensure that subsequent cargo invocations via the wrapper honor usual Debian packaging policies and conventions:

  • use packaged sources instead of fetching from crates.io
  • ensure debug symbols are not stripped out in release mode
  • honor DEB_BUILD_OPTIONS for optimization, LTO and similar settings

Optionally, as part of the auto_test step of the package build, trigger cargo test via the wrapper (either directly or via your package's main build system). You might want to pass all the features used by your package, or test all features.

As part of the auto_build step of the package build, trigger cargo build --release via the wrapper (either directly or via your package's main build system). The resulting binaries should be found in target/<triplet>/release.

As part of the auto_install step of the package build, trigger cargo install via the wrapper.

The cargo wrapper should be used by every Debian package building Rust code!

dh-cargo-built-using

This helper script analyzes the target/.. directory where cargo puts intermediate and final build artifacts, to determine:

  • which non-Rust binaries might have been statically linked (via the build log)
  • which Rust crates might have been statically linked (via the intermediate artifacts)

The found objects are then mapped back to Debian source packages, their licenses looked up via debian/copyright and the corresponding Static-Built-Using and Built-Using substvars are emitted.

In some cases, it might be necessary to patch build.rs scripts to emit licensing details for consumption by dh-cargo-built-using - please follow the instructions if prompted.

dh-cargo-built-using needs to be called after building a binary, e.g. after dh_auto_build or dh_auto_install, and passed the binary package name for which the information should be emitted.

Every package building Rust code should be annoted with Static-Built-Using information!