How does rustup work?

In Linux environment, when I installed rust with rustup I found a phenomenon: there are executable binaries such as rustc in a directory under .rustup, and there are executable binaries such as rustc in the .cargo/bin directory. I'm curious about the whole process, and also what actions rustup performs when I execute rustup default xxx. Can you help me with this, I would like to have a comprehensive and detailed understanding.

The executables for rustc and cargo etc placed into .cargo/bin are just hard-links to rustup. You can execute ls -i in your .cargo/bin directory to see this. For example on my machine (Yours might be a lot shorter; I also have quite a few executables installed via cargo install.)

> cd .cargo/bin
> ls -i1
33691114 bacon*
33691399 bat*
33817918 battop*
33691299 broot*
33691070 btm*
50470873 cargo*
33691280 cargo-add*
33691333 cargo-audit*
33690963 cargo-bisect-rustc*
33690961 cargo-cache*
50470873 cargo-clippy*
33689956 cargo-depgraph*
33691133 cargo-download*
33690640 cargo-expand*
33689998 cargo-feature*
50470873 cargo-fmt*
33691182 cargo-geiger*
33689800 cargo-hack*
33690514 cargo-install-update*
33690529 cargo-install-update-config*
50470873 cargo-miri*
33690000 cargo-nono*
33691304 cargo-outdated*
33691192 cargo-rm*
33691162 cargo-set-version*
33691167 cargo-upgrade*
33691157 cargo-watch*
50470873 clippy-driver*
33691168 delta*
33690351 dust*
33691327 evcxr*
33690144 exa*
33691332 fd*
33689447 htmldiff*
33691190 mdbook*
33691166 mdbook-linkcheck*
33691352 mdbook-toc*
33690045 rg*
50470873 rls*
50470873 rustc*
50470873 rustdoc*
50470873 rustfmt*
50470873 rust-gdb*
50470873 rust-gdbgui*
50470873 rust-lldb*
33689652 rust-reduce*
50470873 rustup*
33691513 sccache*
33690183 sd*
33691664 tokei*
33690706 typos*
33557892 watchexec*
50467718 x*
33817677 xargo*
33817675 xargo-check*
33818402 zoxide*

you see the ID 50470873 a lot of times

> ls -i1 | rg '50470873'
50470873 cargo*
50470873 cargo-clippy*
50470873 cargo-fmt*
50470873 cargo-miri*
50470873 clippy-driver*
50470873 rls*
50470873 rustc*
50470873 rustdoc*
50470873 rustfmt*
50470873 rust-gdb*
50470873 rust-gdbgui*
50470873 rust-lldb*
50470873 rustup*

and these executables are all hard links to the same file, namely rustup! The rustup executable then inspects what the file name of the called executable is, and based on that executes either normal rustup functionality or acts as a wrapper, parsing the optional +stable or +nightly or +1.2.3 kind of argument to determine which version of underlying actual rustc or cargo, etc… binary to execute. Those actual binaries are the files you’ll find in the .rustup directory, under .rustup/toolchains/<name of the toolchain>/bin.

The rustup wrappers in .cargo/bin are also the rustc and cargo etc… binaries that are in your PATH and thus the ones you actually execute by typing rustc or cargo into your command line.

So e.g. calling rustc +nightly …args… on my system would call the aliased/hard-linked rustup executable from .cargo/bin/rustc, which then parses the “+nightly” argument, and call/forwards to .rustup/toolchains/nightly-x86_64-unknown-linux-gnu/bin/rustc …args… on my system. Similarly, because I have stable as default, when executed from a directory without any registered rustup overrides, rustc …args… would call/forward to .rustup/toolchains/stable-x86_64-unknown-linux-gnu/bin/rustc …args…, the same as rustc +stable …args… or rustup run stable …args… would do.

2 Likes

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.