I love Gentoo. I love Rust. How about Rust on Gentoo? Well, I love it, but it’s a little more complicated.

This is a run-down of the steps I ended up taking to be able to manage the Rust installation via rustup on my Gentoo and have Portage use it for ebuilds requiring virtual/rust.

I’m a happy Gentoo user at home, building kernels and emerging all day. I’m also a happy Rust developer who uses both stable and nightly (sometimes several nightlies). When the new Firefox came, I was excited to build it on Gentoo and enabled it with the ~amd64 keyword.

Parts of the new Firefox has been replaced by bits written in Rust, so naturally the Firefox ebuild depends on virtual/rust. This means building the Rust compiler as part of the Firefox build process (the first time only though).

The only problem is I already have Rust installed - in several versions even. So there is really no need for Portage to download and install its own version.

In short, I want to:

  • Manage rustc and cargo with rustup
  • Have Portage pick up the correct rustc and cargo (ie the rustup provided ones)

If no one has told you before, read:

$ man portage

Then read it again. It is a thorough description of all the features of Portage. I found this little nugget describing the package.provided feature:

A list of packages (one per line) that portage should assume have been provided. […] For example, if you manage your own copy of a 2.6 kernel, then you can tell portage that ‘sys-kernel/development-sources-2.6.7’ is already taken care of and it should get off your back about it.

What more do you want? I figured I could put package.provided in /etc/portage but it actually has to go in /etc/portage/profile. I ended up with:

$ tree /etc/portage/profile
/etc/portage/profile
├── package.provided
│   └── rust
└── profile.bashrc

1 directory, 2 files

The contents of /etc/portage/profile/package.provided/rust:

$ cat /etc/portage/profile/package.provided/rust
dev-lang/rust-1.25.0
virtual/rust-1.25.0
dev-util/cargo-0.26.0

It is a requirement that the version number be specified, which I think is fair. Rust and Firefox are slow-moving enough that it shouldn’t be a problem for me to keep up.

I tested this by unmerging virtual/rust, dev-lang/rust and dev-util/cargo, then re-emerging www-client/firefox. Until I figured out how to write the packaged.provided Portage kept wanting to merge the unmerged packages.

After package.provided/rust was accepted, the build failed with the message “Rust compiler not found”. This is because I installed Rust and Cargo as my everyday user, but this is not the user that Portage is running as. Somehow I had to put $HOME/.cargo/bin on the PATH for the build user. I went back to reading man portage.

The solution turned out to be profile.bashrc. I’m not sure this is the best approach, but this is what I have working now:

$ cat /etc/portage/profile/profile.bashrc
export PATH="/home/me/.cargo/bin:$PATH"

STABLE=/home/me/.rustup/toolchains/stable-x86_64-unknown-linux-gnu
rustup toolchain link build-stable $STABLE &> /dev/null
rustup default build-stable &> /dev/null

The calls to rustup are necessary to expose the stable toolchain to the rustc binary found in .cargo/bin. The name build-stable is not important, it just can’t be stable.

That is all it took! Now I have rustup managing the Rust toolchains (it’s a great tool), and Portage happily uses the stable toolchain for packages requiring virtual/rust.