Debian Rust Packaging Policy

Automated Packaging Tools

The "debcargo" automated packaging tool, and the "dh-cargo" buildsystem for debhelper, automate almost all of the requirements of this policy; you should not need to implement most of these requirements manually. This policy documents those requirements, provides accompanying explanation, and specifically highlights any policies not handled automatically.

Terminology

Package naming

Rust library crates must have:

If the crate name contains underscores (_), the source and binary package names must replace them with dashes (-); in this case, dh-cargo requires the package's debian/control file to have an X-Cargo-Crate: field in the source section specifying the upstream name of the crate.

$shortversion is any prefix of $crateversion needed to support co-installation in the case where multiple versions of the same crate are needed to satisfy the build-dependencies of another package. For a crate with semantic version (semver) major.minor.patch, it is recommended to use major (if major != 0) or 0.minor (if major == 0). This supports the Cargo and semver notion of "compatible versions"; see http://doc.crates.io/specifying-dependencies.html#caret-requirements. The latest version of a crate in Debian should use the first naming option above, without any $shortversion.

Rust applications may use any binary package name; they do not need to include a version in the package name or allow concurrent installation of multiple versions. A source package that builds no Rust library packages may use any source package name; a source package that builds both Rust library packages and Rust application packages must follow the naming rules for its source package name and its library package names.

This policy does not yet specify any policies for "cdylib" crates, though they will need to follow all applicable policies for shared libraries.

Crate features

A library crate must also generate binary packages for every Cargo "feature" it declares, named:

depending on the naming choice made for the source and main library packages earlier. Cargo crate names do not allow a plus sign (+) in them, so this package name will not conflict with the package name for any other Rust library crate or feature package. If the feature name contains underscores (_), the corresponding binary package name must replace them with dashes (-).

Each feature package must have a versioned dependency on the same version of the main library package. Each feature package must pull in all the dependencies needed to build a package that depends on that feature of the crate, including any dependencies on other features of the same crate. That is, if a feature of the crate depends on another feature of the same crate, the corresponding feature package for the first feature must have a dependency on the same version of the feature package for the second feature.

In order to avoid too many feature packages, it is allowed to "collapse" some of them together by using Provides. Specifically, if a feature package pulls in the same-or-a-subset-of additional dependencies (i.e. from other source packages) as another feature package, the latter package may Provide: the former package at version (= $crateversion) in which case the former package may be dropped as a real package. The main library package may participate in this process as well.

Package provides

For a crate version X.Y.Z, the main library package must declare Provides:

where up to one of these may be omitted if it is the same name as the binary package.

A library binary package that includes features 0 .. n-1 with crate version X.Y.Z must declare Provides for the following:

for all i in [0 .. n-1], where up to one of these may be omitted if it is the same name as the binary package.

Package dependencies

Library packages must include Depends corresponding to the crate and feature dependencies specified in the crate's Cargo.toml file. These dependencies must satisfy the crate's [dependencies] and [build-dependencies] sections, including any architecture-specific or target-specific dependencies; this allows users and packages to cross-compile for other target platforms, including Windows. However, the dependencies need not satisfy the crate's [dev-dependencies], as those may require experimental or nightly tools for testing or code analysis.

The version constraints on those dependencies must ensure that the version satisfies the corresponding version predicates in Cargo.toml, so that the package can build successfully. However, in some situations, you may want to loosen the version predicates in Cargo.toml and the corresponding version constraints in debian/control. In particular, this can arise if the version constraints across multiple such packages would otherwise require multiple versions of a library crate simultaneously (such as two libraries with the same non-zero major version and different minor versions), while loosening the version constraints would allow packaging just the newer version of that library crate. If you think you may need to change a crate's dependencies, please contact the mailing list first. (These cases most commonly arise because Cargo cannot currently express constraints on external non-Rust packages, including the rustc compiler itself; upstream may depend on an older version because they do not want to require a newer rustc compiler. Debian can use the newer compatible version for all such packages, once Debian packages the newer rustc compiler.)

In order for constraints to be preserved correctly, a Cargo dependency on a given crate must be translated to a single item in the comma-separated Depends: AND-list in the metadata of a Debian binary package. This single item could be a |-separated OR-list, so for example a constraint like cratename (>= 6.1, << 9.5) must be translated to librust-cratename-6-dev (>= 6.1) | librust-cratename-7-dev | librust-cratename-8-dev | librust-cratename-9-dev (<< 9.5), and not for example librust-cratename-dev (>= 6.1), librust-cratename-dev (<< 9.5). debcargo as of version 2.1.0 implements an algorithm to do this. Furthermore, in the translated Debian dependencies it is recommended to use only >= and << constraints and append a ~~ onto version names, in order to better allow for backporting and future patches to the same crate.

Library packages may have Recommends and Suggests for their feature packages.

Library packages may do a test build in dh_auto_test and in these cases they must have Build-Depends on the Rust library and feature packages needed to run this test build, with <!nocheck> annotated as appropriate. Otherwise, they do not need any Build-Depends since they do not build any Rust code when constructing their binary -dev packages (which only contain source code; see below). Application crates must have Build-Depends on the Rust library and feature packages needed to build, with appropriate version constraints corresponding to the version predicates of that crate's Cargo dependencies.

Library package structure

A library crate's main binary package must ship the source code of the crate in the /usr/share/cargo/registry/cratename-version/ directory.

Motivation: At the time of writing, Rust does not have a stable ABI. So, we can't reasonably ship compiled versions of Rust libraries. Instead, library packages ship source code, and application packages build all the library crates they use from source. We will revisit this point, if the situation changes.

The main binary package must also ship a .cargo-checksum.json file in that directory. This file must include a key "package", whose value provides the SHA256 checksum of the corresponding upstream .crate file, as an ASCII hex lowercase string. This file must also include a key "files", with either the value {}, or a value providing checksums of the source files in the package in the format expected for a Cargo directory registry. dh-cargo expects the source package to contain this file as debian/cargo-checksum.json.

This format allows using /usr/share/cargo/registry as a Cargo directory registry with directory sources. For more details on how this mechanism works, see http://doc.crates.io/source-replacement.html#directory-sources.

Feature packages should not contain any files, other than a symlink from /usr/share/doc/packagename to the main library package.

In order to support cross-compiling, each library binary package - the main package plus the feature packages - should use Architecture: any and Multi-Arch: same. (This is not ideal; it is due to a deficiency in the current Debian cross-compiling infrastructure and the Multi-Arch specification.) This applies even if the library crate only runs on certain target architectures or operating systems. Note that if running a test build in dh_auto_test, this might need to be disabled based on the target/foreign architecture (DEB_HOST_ARCH) and unlikely but possibly also the host/native architecture (DEB_BUILD_ARCH).

A higher-level library crate or application crate may use an architecture-specific library conditionally, using Cargo conditionals to only require it on the architectures it supports. In such cases the Depends or Build-Depends may be annotated with architecture-specific constraints. If an application crate depends unconditionally on a non-portable library crate, that makes the application itself non-portable, and the application can use a correspondingly narrower Architecture field.

Package build process

Package builds must not allow Cargo to access the network when building. In particular, they must not download or check out any sources at build time. Instead, builds must use the packaged versions of crate sources, via the corresponding library crate packages, which provide a Cargo directory registry.

Package builds must set $CARGO_HOME to a directory within the package build directory, to avoid writing to the building user's home directory outside the package build directory.

Package builds should run Cargo in --verbose mode. They may set --cap-lints warn to avoid newer compiler warnings breaking old crates, which is mostly relevant for test builds done as part of dh_auto_test but also relevant when building old applications.

Package builds should pass on the Rust equivalent of anything set in dpkg-buildflags. dh-cargo should contain code for the latest version of this; an incomplete list includes -g -O2 and translating LDFLAGS to -C link-arg= arguments.

Package builds should support cross-compiling by passing --target ${DEB_HOST_RUST_TYPE} and -C linker=${DEB_HOST_GNU_TYPE}-gcc. These variables are available from /usr/share/{dpkg,rustc}/architecture.mk. Again, dh-cargo should contain code for the latest version of this.

Maintenance

Library crates should generally have Rust Maintainers <pkg-rust-maintainers@alioth-lists.debian.net> as the Maintainer, to keep them grouped together, and to simplify transitions and rebuilds. Applications may list any maintainer, but please coordinate with the just-mentioned mailing list when packaging new Rust libraries or applications. Application packages may require bin-NMUs to rebuild with newer versions of Rust libraries.

Rust packages must have a debian/copyright file that follows the machine-readable format.

If the license places the restriction such that derivative works in binary form can only be distributed together with the source code, and the license is not one of the reserved short names in the format document just mentioned, then the copyright file must contain a X-Binary-Requires-Source: yes line in the header paragraph. This allows dh-cargo to correctly generate Built-Using fields for packages that are built from this package.

Upstreaming changes

Packaging a Rust library or application may in some cases require changes to its source code, to integrate better with the Debian ecosystem, comply with Debian policies, or otherwise produce better results with packaging. Whenever possible, prefer to integrate such changes upstream, rather than as patches in Debian (upstream-first approach). Whenever possible, seek to improve the debcargo logic or the upstream crate metadata used by that, rather than patching the resulted generated sources (automation-first approach). This makes the Rust and crates.io ecosystem easier to maintain both upstream and in Debian, and avoids technical debt.

dh-cargo

Rust library and application packages should use dh-cargo, to simplify implementation of the Rust packaging policy, including any future transitions or new policy requirements.