Packaging a Rust application
Introduction
Many projects increasingly uses Rust as language for libraries (e.g. rsvg) and a growing number of GUI programs (e.g. Shortwave) or CLI appplications. Most of the GUI programs use meson as build system and gtk-rs. This page tries to give an introduction how you should package such a program. Note: this explicitly is targeted for programs that should maintained standalone (e.g python-cryptography). This is explicitly not intended for crates or binary crates (both published on crates.io), for those see Teams/RustPackaging.
Packaging
First you should check if the program you're trying to introduce has all dependencies in the archive as a librust-foo-dev. To do so, install and run cargo-debstatus on the cloned repo to check what's missing. In case some crates are missing package them with the Debian Rust Team, see Teams/RustPackaging.
If both prerequisites are satisfied you need to "translate" the dependencies from Cargo.toml to build-dependencies in debian/control .
Then you can get the source and prepare the DEP-14 repo as usual.
Mapping rust dependencies to build-dependencies
For instance adw = {package = "libadwaita", version = "0.4", features = ["v1_3"]} translates to librust-libadwaita+v1_3-dev (>= 0.4). To automate this procedure you can install debcargo (>= 2.7.8) and run debcargo deb-dependencies Cargo.toml in the project root. This does not work yet for alpha, beta and rc version as dependencies; workspaces are not yet supported, too. If this is a project mixing e.g. C and Rust you need to point debcargo to the absolute Cargo.toml path (for instance src/foo-rs/Cargo.toml). If you have a dependency in Cargo.toml referencing a git url (e.g. rustdoc-stripper = { git = "https://github.com/GuillaumeGomez/rustdoc-stripper" } replace it with the librust-* debian equivalent in debian/control and patch Cargo.toml with quilt to use a versioned dependency (and hope it compiles). If not, open an issue upstream.
Patching Cargo.toml
You might need to patch Cargo.toml anyway if the version in debian is newer/older than the one specified. The buildprocess reads Cargo.toml so you need to down- or upgrade the version if it's not matching. Newer minor versions are usually fine (i.e. 1.0.3 in Cargo.toml will likely compile against the Debian-packaged version at 1.0.4).
debian/rules
Change the entire file to this:
#!/usr/bin/make -f include /usr/share/dpkg/default.mk include /usr/share/rustc/architecture.mk export CFLAGS CXXFLAGS CPPFLAGS LDFLAGS export DEB_HOST_RUST_TYPE DEB_HOST_GNU_TYPE export PATH := /usr/share/cargo/bin:$(PATH) export CARGO=/usr/share/cargo/bin/cargo export CARGO_HOME=$(CURDIR)/debian/cargo_home export CARGO_REGISTRY=$(CURDIR)/debian/cargo_registry export DEB_CARGO_CRATE=$(DEB_SOURCE)_$(DEB_VERSION_UPSTREAM) export DEB_BUILD_MAINT_OPTIONS=hardening=+bindnow %: dh $@ execute_after_dh_auto_clean: rm -rf debian/cargo_registry execute_before_dh_auto_configure: $(CARGO) prepare-debian debian/cargo_registry --link-from-system rm -f Cargo.lock
lines 3 to 13 just set the relevant buildflags and tell dh to use the cargo wrapper script ( /usr/share/cargo/bin/cargo ). The sources (i.e. the packaged crates) get linked into the debian/cargo_registry directory. prepare-debian additionally takes care of telling cargo to use those crates and build offline. Cargo.lock needs to be removed before building because otherwise you'll get a checksum error.
Note: this is assuming that the buildsystem is automatically detected by dh. If that's not the case you'll need to specify it.
cargo as buildsystem
In case the program itself has no "separate" build system calling cargo (like meson or make) you need to build it with cargo manually. Map the dependencies the usual way. debian/rules needs to specify --buildsystem=cargo. Additionally, touch an empty Cargo.lock and debian/cargo-checksum.json before dh_auto_configure. See tuigreet as example.
debian/control (Static linking)
Since Rust at the moment uses statical linking, Built-Using and X-Cargo-Built-Using need to be set in d/control (similarly to Go).
Like this:
[...] Depends: [...] Built-Using: ${cargo:Built-Using} X-Cargo-Built-Using: ${cargo:X-Cargo-Built-Using} Description: [...] [...]
Note that you need to build-depend on dh-cargo and call dh-cargo-built-using to populate those fields.
Building
If the source is prepared following above steps you should be able to build fully offline. In case you still spot a "Downloading crates" line in the buildlog check the source code if CARGO_HOME gets set at some point. This overrides the one we set so you'll need to patch that (see here).
Notes
If you get stuck at some point ask on the #debian-rust IRC channel. For inspiration you can take a look at the GNOME Rust apps in the archive (like Railway). Do not attempt update any standalone crate part of the gtk-rs stack because a) most likely, it won't work and b) it will break other programs/crates . Instead either wait until the new version lands in unstable or upgrade everything at once. The whole tree can be found here