I had a problem with std
crate not being found. I opened a request for help in the users list and headed over to IRC as well.
For context I installed rust 1.12 from the tarball (and tried using rustup as well) into /usr/local/
I just found with the help of some of the guys in the #rust-beginners channel that the reason std
could not be found was because my sysroot as output by rustc --print sysroot
was /usr/local/stow/yabar/
. I also noticed that if I set the sysroot manually in the rustc command line all was fine and the std
crate would have been found. With this I started scratching my head and went to dig for an answer in the rustc source code.
It turns out that if no sysroot is defined, rustc will try to find a default sysroot.
This is the function that does the job (in src/librustc/session/filesearch.rs
):
pub fn get_or_default_sysroot() -> PathBuf {
// Follow symlinks. If the resolved path is relative, make it absolute.
fn canonicalize(path: Option<PathBuf>) -> Option<PathBuf> {
path.and_then(|path| {
match fs::canonicalize(&path) {
// See comments on this target function, but the gist is that
// gcc chokes on verbatim paths which fs::canonicalize generates
// so we try to avoid those kinds of paths.
Ok(canon) => Some(rustcfs::fix_windows_verbatim_for_gcc(&canon)),
Err(e) => bug!("failed to get realpath: {}", e),
}
})
}
match canonicalize(env::current_exe().ok()) {
Some(mut p) => { p.pop(); p.pop(); p }
None => bug!("can't determine value for sysroot")
}
}
As soon as I saw the function it hit me what the problem was. I installed in my new machine firstly yabar
using GNU stow
. Since /usr/local/bin
didn’t exist, stow
installed yabar
to /usr/local/stow/yabar
and symlinked /usr/local/bin
to /usr/local/stow/yabar/bin
. When I installed rust, the executables were installed to /usr/local/bin
. When this function computes sysroot, it follows the symlinks and determines that rustc resides in /usr/local/stow/yabar/bin/rustc
. And then returns as sysroot /usr/local/stow/yabar
. This is obviously wrong since sysroot should be /usr/local/
. Now, if the function hadn’t followed symlinks I would have had no error at all.
So, my question is, what is the reason for following symlinks when determining the sysroot?