I have had several friends bug me about this on-and-off for a while now, so I decided to write up the experience using non-rustup methods of installing Rust. The following is what I discovered after looking around the Rust Forge and main website, as well as going through the contents of the tarballs and comparing to the contents of the ~/.rustup
directory.
The state of non-rustup installation methods
The download page
The Rust installation tarballs seem a bit neglected. The download page (https://forge.rust-lang.org/other-installation-methods.html) only lists tarballs for the latest versions, and only for full distributions (not components or targets). The link to past releases 404’s (https://static.rust-lang.org/dist/index.html), and there is no visible way to download the targets that don’t have rustc/cargo (looking at x86_64-unknown-linux-musl
in particular), and no way to browse for them because of the aforementioned 404.
The tarballs themselves
The tarballs are in a layout that requires the use of an ./install.sh
script to place them in a configurable prefix (default /usr/local
). It goes beyond just copying files into place, however, and there are a few stateful bits. The installer writes manifest files with absolute paths, which seem to only be used for the uninstall script. On linux it will also try to create an ld.conf.d
file (but only if you installed to the standard prefix?) and then run ldconfig
(regardless of where you installed), which will fail unless you’re running with sudo
. This part seems extra weird to me as the rustup
version seems to live with user-only installs just fine and doesn’t have to mess with ldconfig
.
Why should we care?
Rustup is handy, right? I think rustup is a great and useful tool as a Rust developer. There are cases where we should have a better story around installing one particular Rust version and leaving it at that. Build and CI springs immediately to mind; if you care about reproducibility you want to also make sure you’re using an exact version of a toolchain in addition to an exact version of a codebase. I believe it’s also an extra inhibition to people finding a Rust project, getting interested, and trying to compile from source.
I’ve also talked to several people who balk at the standard curlbash installation method for rustup and are also then nonplussed at having to click through several steps (while being reminded that rustup is a thing you should use) to get to the tarballs. Hopefully they then don’t notice the broken links to the past versions or the inability to add targets after that.
Why can’t you just use X?
Docker
Using docker to get a specific Rust version to build with is like using a (hard-to-debug) sledgehammer to kill a fly. Besides, if we simplified per above, it would be simple to install Rust yourself inside the container if you wanted to start from your own base to build. I prefer the model of starting with something I know and adding other stuff, rather than the docker solution which would be starting with someone else’s base and then adding/removing.
Distro Packages
- No guarantee they will have the version you request to build with
- No guarantee the version that you build with on distro version X will exist on distro version Y
- No guarantee the compiler versions will be the same across distros, because of vendor patchsets
- No guarantee the components/targets you want will be available via the system package manager
- Juggling package managers and package names across distros
The tarballs that exist today
It would be nice if I could glue things together in such a way that I can do the minimal amount of bash-calling and privilege-escalation before starting my build, which is the only place I’m hoping or expecting to see things fail. If I can download a tarball (or stash it locally), hash it to verify I got what I expected, and just un-tar and build, I’d save a lot of boilerplate. I’m also paranoid about whether or not that ldconfig
thing is actually necessary so I can’t just install it to /tmp/rust
and then re-tar.
Rustup
See previous. If I don’t like running an install step from a tarball that I can hash I’m not going to want to introduce non-determinism by curlbashing rustup and having it install things.
What if tarball users aren’t real and we made packaging better for nothing?
Even if I’m 100% wrong about people being put off by rustup or tarball hunting, I think we could make a couple changes and benefit both users of rustup and of tarballs and come closer to unifying the two so we aren’t bifurcating our build process or splitting our attention.
-
Tarballs should be self-contained and relocatable. Their structure should be something like
rust-1.31.1/ bin/ lib/ share/ etc/
so you could un-tar it somewhere, update
$PATH
to point at therust/bin
dir, and away you go. This is how golang tarballs work, and it is rather handy. Want to uninstall?rm -rf
. Want to update? Eitherrm -rf
and un-tar the new one, or untar to a new path and update a symlink. Want to have multiple installs? Go ahead! -
Components/targets are also tarballs that have the same structure. Targets would basically be a tarball with
rust-<version>/lib/rustlib/<target>
. Adding components is overlaying tarballs. I assume this is pretty close to how components actually look today as this is roughly whatrustup
does (I can’t check due to the web directories being unbrowsable). -
Downloads page should have an
*-all.tar.gz
tarball that basically contains the components that the tarball today does (cargo, rustc, rls, docs, clippy, rustfmt, std, llvm-tools, rust-analysis), except self-contained as in #1 (I also wouldn’t mind a*-min.tar.gz
version, but I’m not sure what constitutes a minimum useful set) -
Rustup can now use these tarballs as its components to add/remove. Removal would have to be done by manifest-tracking files upon install (un-tar’ing) but that appears to be how it does it today anyway?
-
(Moon Shot) Rustup could assume control of an existing install. If someone installed via tarballs and later wanted to get on the rustup train, you could point rustup at the existing install and it could just assume ownership and start tracking that version. It would be no longer necessary to have someone blow away a Rust installed via tarballs before they could use rustup.
What about people currently using tarballs?
If this is a concern (and I’m not sure if people are using tarballs by scraping for latest and just following the same install procedure), leave the install.sh
script in the tarball. It can do exactly what it does today, moving things to different prefixes or paths. Maybe remove the ldconfig
thing though.