Packaging workspaces and crates not published on crates.io

In an ideal world, all crates are published on crates.io, so then can be packaged one by one. However, the reality is different.

Some projects pack tens of internal crates in a workspace. Some still publish on crates.io, but it's quite a hassle to packaging them one by one. Some don't, often seen in projects that build programs - these internal crates are not used outside.

Some projects do not publish on crates.io. For programs, this doesn't matter. For libraries, however, their name scheme has yet to be decided, since the librust-*-dev namespace is reserved for libraries from crates.io. Luckily, there is currently no need to.

General setup

This kind of packaging falls back to "traditional" ways in Debian. This assumes you are already familiar with general Debian packaging. Experience with the single crate process isn't strictly needed but is helpful.

  1. Import upstream source by either cloning the upstream repository, gbp import-orig, or ways you prefer.

  2. Prepare the common things in debian/ as usual.

  3. Check packaging status of dependencies. There is currently no ready-made tool for this, but you can gather all [dependencies] and [dev-dependencies] in Cargo.toml of these internal crates into an empty cargo project, and run cargo-debstatus there.

  4. Add them as Build-Depends along with rustc and cargo in debian/control.

  5. Prepare a .cargo/config.toml replacing source.crates-io to the Debian registry:

     [source.crates-io]
     replace-with = 'debian'
    
     [source.debian]
     directory = '/usr/share/cargo/registry'
    

    and put it in place before build (in debian/rules):

    execute_before_dh_auto_configure:
    	mkdir -p .cargo
    	cp debian/cargo-config.toml .cargo/config.toml
    

    You may want to add .cargo/config.toml as a clean target.

  6. To follow Multi-Arch, use the variables provided by rustc:

    include /usr/share/rustc/architecture.mk
    
    CARGO_BASE_ARGS= --release --target $(DEB_HOST_RUST_TYPE)
    
    override_dh_auto_build:
    	cargo build $(CARGO_BASE_ARGS)
    
    override_dh_auto_test:
    	cargo test $(CARGO_BASE_ARGS)
    
  7. Patch the source as needed.

No need to publish internal crates

This is the easy part. After adding needed dependencies as B-D, patching them to use versions in Debian, patching out unavailable dependencies and feature depending on them, just run cargo build in debian/rules and install the resulting binary(-ies).

Publish internal crates

First, add a Package stanza for each of them in debian/control, which Provides their versioned virtual packages, and install to their respective location at /usr/share/cargo/registry/$crate-$version.

Then, consider these situations:

  1. Crates in workspace are released in lockstep, sharing the same version for each release.
  2. They only reside in a workspace, but are released in their own pace.

There's not much to say about (1). For (2), though, there is a problem: the source package, or the workspace, has a version. Each binary package, or crate, also has their own version. The only known way to achieve this is to dpkg-gencontrol/dh_gencontrol for each binary package; see rust-curve25519-dalek for an example.

Then it's the tiresome work of keeping B-Ds, Packages, and Depends in sync. There hasn't been strong urge to write a tool for this.