Getting started

Welcome to Rust, and packaging all things Rust in Debian! Like for other languages, it's recommended to first get an idea of what Rust is if you haven't.

Rust is famous for its comprehensive and well written documentation; check out the official learning materials, including The Rust Programming Language. There's also a crash course on the language grammar at Learn X in Y minutes, though it doesn't cover many aspects integral to the Rust ecosystem.

Rust has an extremely streamlined and easy to use build system called cargo. Most of the time, just run cargo build to build a program (in development mode; to build in release mode, add --release). There is also cargo check, to check if the code is correct; and cargo run, to run a built program (after building it if not already; likewise, add --release for release build). Dependencies are managed consistently. There's no need to fight with the build system like CMake.

Like other languages that are normally compiled, Rust crates are thus split into two categories: binary (programs only, as of now) and library. Binary crates are more or less simple: point cargo to Debian's crate registry (using source replacement), run cargo build --release, install the resulting executable, and you are done. Libraries, on the other hand, are more involved.

What is a crate? TRPL covers it in detail, but in the context of Debian Rust packaging, we often use package to refer to a Debian package, and crate to refer to a Rust package.

Things to know

Before diving into packaging the new shiny tool, however, some things need to be known:

Static linking

In contrast to the C/C++ world, which is the source of a norm in Linux/*nix that is dynamic linking, Rust, like Go, is statically linked. Advantages and disadvantages aside (both linking strategies have both), this means Rust libraries are not packaged like C/C++ libraries, which carry foo.so objects; but rather, they are simply source files, installed to a specific location. (Rust could build as dynamic libraries, "dylibs" by its jargon, but the support is not as mature as static linking, and has yet to see an example in Debian.)

Features, SemVer, and encoding in virtual packages

Below crates, they have another level of optional compilation and dependency, called features. With presence and absence of the #[cfg(feature = "feather")] macro, certain parts of the source code could be included or excluded in compilation. They can also enable or disable optional dependencies.

To make features work in Debian, they currently are (mostly) encoded as virtual packages (as per policy): librust-foo-dev Provides librust-foo+feather-dev, encoding its "feather" feature. A package who Depends on it semantically "depends" on that feature. Sometimes, though rarely, there is a feature dependency loop, then we have to split feature packages into real ones (i.e. Package: librust-foo+feather-dev).

Another thing encoded in virtual packages is semantic versioning: librust-foo-1.2.3-dev Provides version 1.2.3 of the "foo" crate. This is due to the semantic differences between (cargo's flavor of) SemVer and Debian version specifiers. A package who Depends on librust-foo-1.2-dev semantically "depends" on at least version 1.2 of the "foo" crate.

Combined, librust-foo+feather-1.2.3-dev Provides the "feather" feature of version 1.2.3 of the "foo" crate.

This sure leads to exponential bloat of the Provides field. Do you have a better idea? Don't hesitate to talk to us ;)

Patching, a lot of patching

Due to various reasons, we can't always just use the original sources, and need to patch the them. The most common ones are 1. dependency version mismatch, 2. removing things Debian don't have or need, 3. adapting to Debian specific things, 4. devendoring and excluding non-packageable content.

This has a minor consequence: cargo projects have a Cargo.lock file, "locking" the versions and checksums of dependencies, a security measure. However, we often don't have the pristine sources in Debian. Thus, we remove the lock file when building, instead relying on Debian package checksums.