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

Upstream Guidelines

This section of the Rust team book gives a quick overview over things upstream developers can do (or should not do) to make packaging their crates / projects written in Rust easier for Linux distributions like Debian. Most the the tips here will also improve the robustness outside of distribution related packaging efforts, e.g. by extending test exposure which often finds issues/buggy behaviour.

We actively invite upstreams to give us feedback on these guidelines!

Applicable to all crates / Rust code

Run your CI on something other than x86_64/aarch64

Debian is released on a wide range of architectures, with an even bigger set covered by its "Ports" effort. Running CI on at least a 32-bit architecture, possibly even one with Big-Endian support helps discover portability issues.

Run your CI with non-default feature combinations

Debian packages (by default) will test the following feature combinations when a crate is packaged:

  • all features enabled
  • no features enabled
  • the default features enabled
  • each feature enabled on its own, with default features disabled

Many crates exhibit test suite failures when tested in this fashion, usually caused by missing #[feature] annotations in the test (or regular) code.

Ensure your test suite can run as published on crates.io

Debian uses the published crate tarball from crates.io as input for packaging.

If this published version of the crate is lacking test input data, or the test suite relies on test helper crates which are not published, some or all of the tests cannot be run as part of the packaging effort. The resulting package will have a higher chance of being buggy as a result.

If it is absolutely not possible to publish the full test suite, please ensure that cargo test does work on the published crate nevertheless.

Avoid dependencies on alpha/../pre-release versions

Unless your crate is currently itself released with an alpha/../pre-release version, do not use such versions of your dependencies. Distributions will (usually) not package such versions since they are not ready for release yet.

Avoid nightly/unstable features

Unless absolutely required, do not rely on nightly or unstable compiler features or crates that require them. If you do, please make it possible to disable such requirements by patching out features.

Packaged toolchains do not support such features.

Avoid duplicate dependency versions in your dependency tree

Having multiple incompatible versions of a crate in your transitive dependency tree makes transitions in distributions harder.

Be conservative with MSRV, dependency versions and semver breaks

Distributions will usually not have the latest version of the toolchain or crates already packaged. By being conservative with MSRV bumps, tracking the actually required minimum versions of dependencies instead of blindly bumping to the latest, and avoiding frequent semver-breaking version bumps of your crate(s) you can help keeping downstream patching and churn to a minimum.

Having a documented MSRV policy will also help packages when considering whether to package your particular crate/project.

Document which features are considered part of your public crate interface

Documenting features which only exist for technical reasons (like usage in CI, fuzzing, ..) or are considered unstable and not covered by semantic versioning both helps potential dependants and distribution packagers.

In general, try to keep the amount of features reasonable, and ensure you use the correct syntax to avoid exposing optional dependencies as features by accident.

Specific for -sys / FFI crates

Bundled C (library) source code

Many -sys crates include a copy of the library they are linking with. These sources are usually stripped by distribution packagers, since distributions want to link (only) with the version of the library shipped in distribution packages.

Ensuring that there is an easy, tested way of building in the absence of bundled sources makes packaging and updating such crates a lot easier.

Pre-generated bindings

For similar reasons, pre-generated bindings are usually regenerated at package build time in distributions. Ensuring that there is an easy, tested way of regenerating bindings makes packagers' lifes easier.

Cross-building

If possible, testing cross-builds and trying to make them work out of the box will allow easier bootstrapping of new architectures.

Specific for applications written in Rust

Generate and ship a man page for CLI applications

If using clap, this can be done using clap_mangen. Writing a man page manually is also an option. Generating it from --help output usually means breaking cross builds, unless it is done via test/CI and not as part of the regular build.

Generate and ship shell completions for CLI applications

Similar considerations as for man pages apply. For crates using clap, this can be done using clap_complete.

Specific for cdylibs

TODO