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 build debcargo from this MR and run debcargo deb-dependecies Cargo.toml in the project root. This does not work yet for alpha, beta and rc version as dependencies and workspaces are not yet supported, too. 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.

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

Note: this is assuming that the buildsystem is automatically detected by dh. If that's not the case you'll need to specify it.

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: [...]
[...]

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 and touch an empty Cargo.lock and debian/cargo-checksum.json before dh_auto_configure.

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