Hey, Rustland.
You want to have a perfect Rust experience on your platform, and so do I.
But Rust needs your help to understand how to package Rust well and consistently across a variety of package managers.
This is a complicated topic. I’m going to describe some simple objectives, ask a bunch of questions, then try to organize the resulting information into a plan with discreet steps that we can take to harmonize the Rust packaging story.
I’ve already pinged the following individuals that I know are involved in packaging Rust to alert them to this thread.
- Debian: Angus Lee, Luca Bruno, Sylvestre Ledru
- Fedora: Fabian Deutsch, Radek Vokal
- Ubuntu: Hans Hoel.
- Chocolatey: Mike Chaliy.
- Gentoo: Jauhien Piatlicki.
- SUSE: Kristoffer Gronlund.
- Arch: Alexander Rødseth.
- Windows: Vadim Chuganov.
- Homebrew: Nobody (Who will represent Macs?!).
Objectives
I’ll refer to the Rust project and its artifacts as ‘upstream’ and everything else as ‘downstream’.
Here are some of the goals I think Rust has:
- Getting Rust and Cargo into the main package archives of a major Linux distribution.
- Packages for Cargo always available where Rust packages are.
- Downstream packages organized similarly to upstream packages.
- e.g. we currently have distinct rustc, cargo, rust-docs packages, though they are almost always installed as a combined rust package.
- In Debian I might expect the ‘rust’ package therefore to pull in the same sub packages.
That’s really the important stuff. We want Rust to be available, and with consistent quality, where people expect. Let’s clear the way.
Some of the topics I’m imagining worth working out are bootstrapping, package organization, trademark matters, maintenance responsibilities, interactions with cargo’s on package management, multirust, side-by-side installs, cross-compilation, std packaging, cargo versioning.
I’m sure you have others.
I’d like to figure out the basic requirements here, draft some Rust packaging guidelines and a plan to fully implement them both upstream and in one major downstream Linux distro.
Discussion Topics
-
What is the division of packages that make up the Rust system? I would like this to be consistent(ish) across distributions. Upstream rust, for example currently has ‘rustc’, ‘cargo’, and ‘rust-docs’, and will have ‘rust-std’ (potentially many for arbitrary targets) soon. For distribution we package all these into a single ‘rust’ package so most people never see the subpackages. Debian already has discreet rust-lldb and rust-gdb packages so they can avoid making rust itself dependent on gdb/lldb. Should upstream make this distinction as well? What other considerations does downstream have when deciding the division of packages?
-
What are the unique documentation requirements downstream? The upstream doc package puts the license in /usr/local/share/doc/rust and the HTML docs in the ‘html’ subfolder thereof. It seems likely to me that some distros want to handle their docs in a consistent, distro-specific way.
-
How should multirust be packaged? Toolchain switchers for Ruby are packaged, but multirust in particular is specifically designed to install from the upstream binaries. What is the role of such a tool in a distribution? Is, e.g. RVM modified to work with the distribution package system?
-
Similarly, what are the requirements for side-by-side (SxS) installation in distros? It’s common to see many packages for gcc, with various names, often installing binaries with names like
gcc-4.9
to distinguish from the ‘default’ gcc. Does Rust need to be able to producerust-1.1
andrust-1.2
compilers that can be installed next to each other without interfering with the others’ operation? We’ve put no thought into this upstream. -
How do we need to improve Cargo releases? Right now new Cargo releases are tagged every release cycle, but crucially we don’t actually pair those Cargo commits with the Rust releases, so the Cargo that comes with Rust will have a version number different from the previous Rust release, but it is not the same Cargo commit as tagged as a release. We also don’t distribute source tarballs for Cargo releases. I assume packagers would be much happier if we bumped Cargo versions in lock-step with Rust and made sure the correct builds of Cargo get released with Rust.
-
Bootstrapping Rust. Bootstrapping Rust requires Rust. This is not uncommon for compilers, but being a new compiler, getting every distro that wants to provide Rust doing their own self-sufficient bootstrapping is hard. It doesn’t help that upstream bootstraps off of arbitrary snapshots, not stable releases. Debian currently bundles a stage0 blob with the source. This is apparently acceptable in a broad sense, but they do not like it. Don’t know what other distros are doing here.
It seems to me like we might be at a stage where we could insist on bootstrapping from the previous release (and only the previous release), which is only 6 weeks in the past. I used to be opposed to this as too restrictive, but this is a major downstream pain point and we can make some concessions here. My concern with this strategy though is that distros would still need to keep up with our upgrades or risk missing the next snapshot and falling off the bootstrapping wagon, and many distros are not in the habit of updating their software every 6 weeks.
A slight alternative to this might be to provide a little script that bootstraps accross multiple snapshots, a chain of snapshots, and we could guarantee that there’s an unbroken chain of bootstraps from, say version N-4 (6 months). That way we could continue doing snapshots at arbitrary points in time, as long as we ensured that there is a snapshot that corresponds to every stable release. This would give distros a grace period wherein they aren’t required to stick to the Rust upgrade schedule.
-
Bootstrapping Cargo. This often seems to be the hardest part of porting Rust to new systems. Both Debian and *BSD are using cargo-bootstrap.py to build Cargo without a pre-existing Cargo. Is this the right solution? Should we officially support building Cargo without Cargo to make this easier?
-
Packaging Cargo-built Rust crates. Cargo is a package manager. How do we make it interoperate with the native package manager? I know this is a problem that most modern language ecosystems face, and solve to greater and lesser degrees. Which systems are doing this right and why? I know almost nothing of the problems here.
-
The standard library is going to soon be packaged independently from the compiler, in order to allow install of arbitrary cross-compilation targets. After this we’ll likely have a package called ‘rust-std-{version}-x86_64-unknown-linux-gnu’. An important change after this is that a single rust installation may be installing packages with more than one target triple (i.e. an install will have ‘rustc-{version}-x86_64-unknown-linux-gnu’, ‘cargo-{version}-x86_64-unknown-linux-gnu’, etc. but also ‘rust-std-i686-unknown-linux-gnu’). I’m not sure how such a scheme maps to downstream package managers. Would, for example, Debian package a cross-std as something like ‘rust-std-i686’?
-
LLVM packaging. It’s long been a concern that Rust uses its own fork of LLVM. Recently though Rust’s fork diverges little from upstream LLVM, only doing a few optimaztions that upstream doesn’t want. Rust is, in theory, compatible with stock LLVM 3.7 (and even earlier), though upstream never tests this. Which distros care about being able to use the system LLVM? A relatively low-maintainence thing upstream could do to make this easier might be to set up automation to guarantee that Rust builds with some stable release of LLVM.
-
Default CPU features. @gus pointed out recently that rustc’s default code generation is for i686 while Debian’s 32-bit x86 distro targets i586-class machines. Should we be adjusting the target specs for these systems? How? Any insight into how other compilers deal with this?
-
Distro-specific linker flags. @gus (Debian) also pointed out that there may be need for distros to always pass custom flags to the linker. I don’t have any further information about this. What’s the use case?
-
Upstream we use the custom rust-installer as our packaging system. Part of the intent here, as seen in rust-packaging, is that this format is simple enough to be used by downstreams to derive their own packages. I’m interested in whether packagers are using the rust-installer artifacts as intermediates in their own packaging, and if not, how they are selecting the correct set of artifacts to package. If deriving downstream packages from our own packages isn’t a viable solution, what else might we do to ensure that the contents of packages are consistent across distributions?
-
What sort of packaging guidelines can the Rust project provide, and will downstream care? I’m imagining specifying the package division, package names, the prefered scheme for packaging cross-std, bootstrapping strategies, branding and trademark guidelines.
-
How can we help downstream stay up to date? Is there anything we can do in rust-packaging, like maintain and test packaging rules?
-
Many proprietary projects (think Chrome) produce ‘universal’ debs/rpms, where they are compiled (like our upstream bins) to be maximally compatible, at the expense of distro packaging guidelines, and distributed by upstream. This seems like a good idea for us to do, particularly before Debian and Fedora have gotten their packaging stable and they trickle down to their own downstreams. Is there any desire for upstream Rust to produce such packages?