Debian Rust Packaging Policy (draft)

The Debian Rust team has the pieces in place to start packaging Rust library crates and applications written in Rust. We have a packaging tool, debcargo, which automatically translates a Cargo crate into a Debian source package; we then have a Debhelper buildsystem, dh-cargo, which handles the package build.

We’ve drafted a preliminary packaging policy, and we’d love to get the Rust community’s feedback on it.

A few highlights:

  • Debian packages have to build using only other Debian packages, and must not access the network at build time. So, we need to package library crates for Rust applications to build-depend on. This works similar to vendoring, but on a distribution-wide scale.
  • Because Rust doesn’t have a stable shared-library ABI, and we don’t want to rebuild every Rust library package for every architecture every time we upload a new version of rustc, we package library crates as source code, installed into /usr/share/cargo/registry/cratename-version/. Thus, the Debian “binary” package for a library crate contains the same source as the source package.
  • We use a Cargo directory source to allow Cargo to build applications using the library crate sources.

We hope to use these tools and this policy to start packaging Rust applications for Debian (starting in experimental at first). High-priority Rust applications that we want to package include cargo itself (already packaged using vendoring within the source package, but this would greatly simplify it), debcargo, rustup, and ripgrep. We’d welcome any feedback on this approach.

cc: @lucab @alexcrichton

17 Likes

https://wiki.debian.org/Teams/RustPackaging/Policy

If the feature name contains underscores (_), the corresponding binary package name must replace them with dashes (_).

Maybe should be fixed to "dashes (-)"?

3 Likes

Good catch, thanks! Fixed.

Most of it looks good and thought through to me!

A few thoughts:

I’m a little afraid that the number of binary packages are going to explode if all features need to have their own crate; and some features might not be relevant (e g if the feature only makes a difference on non-unix operating systems), perhaps the policy should be relaxed to a library crate can instead of a library crate must?

Another question is if there’s a recommendation to use crates.io or github as the primary upstream for a crate?

And last but not least; if one wants to maintain a debian package that corresponds to one’s own crate (e g), are there sponsors ready and waiting? :slight_smile:

We want to support building for non-UNIX OSes too; people can use a cross-compiler to build for Windows, for instance. Consider packages like gzip-win32; we'd like to support people building packages like that for Rust applications.

Only a fraction of crates use features, and of those that do, many of those features will just become Provides from the main package (if they don't have any additional Depends). When I went through everything needed to package ripgrep, I ended up with about 40 crates, but only a few additional feature packages.

crates.io in the majority of cases; debcargo automatically downloads .crate files from crates.io and uses them as the .orig.tar.gz source. In rare cases, it may make sense to use something else as the primary upstream, such as if you absolutely have to package a git snapshot, or if the package has Rust as just one part of its build process (Firefox, for instance).

If you're interested, please contact pkg-rust-maintainers@lists.alioth.debian.org and let us know; we'd love to know what crates people would like to see packaged, and we'd always appreciate the help.

Thanks for the answers! Now I have another question:

If a crate bar 1.0 has a feature Foo which requires libfoo-dev, then that results in two binary packages, librust-bar-1-dev and librust-bar-1+foo-dev. The question is whether librust-bar-1+foo-dev will be a package with no contents, depending only on libfoo-dev and librust-bar-1-dev, or if librust-bar-1+foo-dev will contain source files as well (and if so, in the /usr/share/cargo/registry/bar-1+foo/ directory, or…)?

None of the feature packages contain any files; they only exist to provide dependencies. I added a mention of that to the policy.

1 Like

Thanks for doing this @josh. This is some difficult work. The policy looks how I might have expected it to.

My primary concern with Debian packaging library crates is that they do not interfere with crate resolution for Rust developers, that these packages are only used for building Debian-packaged Rust applications, and it looks to me like that is the case.

@brson You’ll only get the packaged versions of the crates if you explicitly use a directory source referencing them. We won’t configure cargo to use them by default.

Thanks for your review!

1 Like

I’m not sure whether this is relevant to your immediate use cases, or only something for longer term goals, but cargo crates and cargo packages are different things.

1 Like

This looks really good, @josh. The only thing that wasn’t totally clear to me was the rationale around the “feature-enabled” versions of crates – in particular, the resulting dependency graph. But probably this is just lack of familiarity with Debian packaging on my part.

Interesting distinction. So, a .crate file contains the source for a Cargo “package”, not a Cargo crate?

Suppose you have a crate "useful-structures", which contains a variety of data structure implementations. If you enable the "hash" feature, it includes some hash tables, and depends on the fnv crate. An application crate wants to use those, so in its Cargo.toml, it depends on the hash feature of useful-structures.

The corresponding Debian package for the application will have a Build-Depends on librust-useful-structures-1+hash-dev. librust-useful-structures-1+hash-dev will have a Depends on librust-fnv-1-dev. If useful-structures wants to switch from fnv to seahash, it can do so, and the application just has to rebuild to start using the new version.

Does that help?

(To avoid a proliferation of feature packages, we only generate distinct feature packages for features that have additional dependencies. Feature packages that don't have additional dependencies still exist in the packaging system, but as Provides from the main package; that allows other packages to have Depends or Build-Depends on it by that name, without actually having a separate package. For instance, most library packages librust-foo-1-dev will provide librust-foo-1+default-dev.)

2 Likes

One could make features available by having the -dev just go ahead and pull in all potential dependencies, and let Cargo figure out what it actually wants. As I see it, the +feature subpackages only serve to minimize the build root when those dependencies aren’t actually needed. That’s an optimization, but not a necessity.

Anyway, good work on all this! I’m watching this closely for Fedora inspiration, as we haven’t formed proper packaging policies yet. I’m not sure there’s enough code that could be shared with a theoretical rpmcargo sibling to debcargo, but we can still try to cross-pollinate ideas. For instance, I thought it was a neat trick that even for binaries you use cargo install from the directory registry, to dodge the various ways that Cargo treats local-path builds differently.

2 Likes

Yes, and crates.io distributes cargo packages, not cargo crates. Though obviously those packages contain crates.

Names are hard.

One could make features available by having the -dev just go ahead and pull in all potential dependencies, and let Cargo figure out what it actually wants. As I see it, the +feature subpackages only serve to minimize the build root when those dependencies aren't actually needed. That's an optimization, but not a necessity.

True, but in some practical cases it becomes nearly a necessity to avoid a massive excess in dependencies.

Anyway, good work on all this! I'm watching this closely for Fedora inspiration, as we haven't formed proper packaging policies yet. I'm not sure there enough code that could be shared with a theoretical rpmcargo sibling to debcargo, but we can still try to cross-pollinate ideas.

I think we could share a great deal, actually. We can share all of the downloading and parsing code, and the calculation of dependencies and packages, and just abstract out the writing of the source package. In the code of debcargo, the code we'd need to split out starts with a braced block inside do_package; imagine keeping everything in do_package above that, and factoring out the code below that into a write_debian_source or write_srpm function.

Right now, those two blocks share a huge number of local variables; we'd need to factor that out into a "Package" structure instead, likely using a builder pattern.

2 Likes

Thanks, that makes sense to me!

Seems to be a problem with that email address. Any mail sent to it gives a delivery failure response.

1 Like

Good catch, thank you. I corrected the email address in that post, to pkg-rust-maintainers@lists.alioth.debian.org.

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.