How does packaging Rust binaries for Fedora work?

So, I’m trying to figure out how exactly Rust packaging works, and it’s a bit…confusing.

To start with I went to the packaging guidelines and found a page for Rust, but it says:

This document is applicable only for Fedora Rawhide. Stable releases do not contain any crates. However, this document can be used to build modules with Rust applications (with crates filtered out).

Thus, I decided to open up the spec file for a Rust package, at which point things became…more confusing:

  • All the packages under modules/ are labeled as “demodularized”.
  • The standard RPMs have no branches for anything post F29, so I’m guessing stable releases follow master? But…
  • All of the packages I found specified crates in BuildRequires, e.g. fd-find, ripgrep, exa.

True to the packaging guidelines, none of the crates seem to be available:

$ sudo dnf whatprovides 'crate(grep/default)'    
Last metadata expiration check: 4:43:15 ago on Wed 26 Aug 2020 10:45:56 AM CDT.
Error: No Matches found

As expected, Rust packages can’t download from the network either:

$ rpm --eval '%cargo_prep'
(
set -eu 
/usr/bin/mkdir -p .cargo 
cat > .cargo/config << EOF 
[...]
[source]

[source.local-registry]
directory = "/usr/share/cargo/registry"

[source.crates-io]
registry = "https://crates.io"
replace-with = "local-registry"
EOF
/usr/bin/rm -f Cargo.lock 
)

With all of this in mind, I’m honestly at a loss as to how you would package a Rust binary. What am I missing here?

2 Likes

This document is applicable only for Fedora Rawhide. Stable releases do not contain any crates. However, this document can be used to build modules with Rust applications (with crates filtered out).

This is no longer accurate. Rust packages are no longer shipped as modules.

This is, however, expected, unless you run rawhide:

sudo dnf whatprovides 'crate(grep/default)'

Because crates are only available on rawhide, while binaries are built via a special process for stable releases as well.

So to start off, I would recommend to follow the packaging Guidelines for Rust, but target fedora rawhide first. Once that works, you can take the necessary steps to build your binary on stable releases as well. People who can help you with that usually hang out in the #fedora-rust IRC channel on freenode.

Hmm interesting, I’ll definitely have to check out that IRC channel.

So assuming I target rawhide initially, how would I build it for my personal installs? Basically, I’m looking to rewrite a Go tool in Rust (turns out I hate Go, and I hate packaging Go, and I’m guessing the latter’s myriad of different library versions across different Fedora releases is why Rust crates all target rawhide), and this is something that generally works with the system in such a way that the best way for me to test it is just to install it locally. Thus, I’d have to build Fedora 32 packages early on, so exclusively targeting rawhide wouldn’t be super practical unless I feel like doing all my testing in Vagrant…

For building RPM packages, I recommend using mock, with the rawhide buildroot as target (mock -r fedora-rawhide-x86_64 ./path-to.src.rpm). You can also let a tool handle the initial creation of your .spec file (rust2rpm).

Targeting stable fedora releases is a bit difficult outside of fedora infrastructure, unfortunately, since rust crates are only packaged for rawhide :frowning:
However, you can try installing the RPM packages that you built against rawhide on fedora 32. Most of the time, that should work fine (rust is statically linked after all).

1 Like

Ack, this’ll be interesting to work with. Thanks for the replies!