|
1 |
| -//! FIXME: write short doc here |
| 1 | +//! Loads "sysroot" crate. |
| 2 | +//! |
| 3 | +//! One confusing point here is that normally sysroot is a bunch of `.rlib`s, |
| 4 | +//! but we can't process `.rlib` and need source code instead. The source code |
| 5 | +//! is typically installed with `rustup component add rust-src` command. |
2 | 6 |
|
3 |
| -use std::{convert::TryFrom, env, ops, path::Path, process::Command}; |
| 7 | +use std::{convert::TryFrom, env, ops, path::PathBuf, process::Command}; |
4 | 8 |
|
5 |
| -use anyhow::{bail, format_err, Result}; |
| 9 | +use anyhow::{format_err, Result}; |
6 | 10 | use arena::{Arena, Idx};
|
7 | 11 | use paths::{AbsPath, AbsPathBuf};
|
8 | 12 |
|
@@ -51,92 +55,95 @@ impl Sysroot {
|
51 | 55 | }
|
52 | 56 |
|
53 | 57 | pub fn discover(cargo_toml: &AbsPath) -> Result<Sysroot> {
|
54 |
| - let src = get_or_install_rust_src(cargo_toml)?; |
| 58 | + let current_dir = cargo_toml.parent().unwrap(); |
| 59 | + let sysroot_src_dir = discover_sysroot_src_dir(current_dir)?; |
| 60 | + let res = Sysroot::load(&sysroot_src_dir); |
| 61 | + Ok(res) |
| 62 | + } |
| 63 | + |
| 64 | + pub fn load(sysroot_src_dir: &AbsPath) -> Sysroot { |
55 | 65 | let mut sysroot = Sysroot { crates: Arena::default() };
|
| 66 | + |
56 | 67 | for name in SYSROOT_CRATES.trim().lines() {
|
57 |
| - // FIXME: remove this path when 1.47 comes out |
| 68 | + // FIXME: first path when 1.47 comes out |
58 | 69 | // https://github.com/rust-lang/rust/pull/73265
|
59 |
| - let root = src.join(format!("lib{}", name)).join("lib.rs"); |
60 |
| - if root.exists() { |
| 70 | + let root = [format!("lib{}/lib.rs", name), format!("{}/src/lib.rs", name)] |
| 71 | + .iter() |
| 72 | + .map(|it| sysroot_src_dir.join(it)) |
| 73 | + .find(|it| it.exists()); |
| 74 | + |
| 75 | + if let Some(root) = root { |
61 | 76 | sysroot.crates.alloc(SysrootCrateData {
|
62 | 77 | name: name.into(),
|
63 | 78 | root,
|
64 | 79 | deps: Vec::new(),
|
65 | 80 | });
|
66 |
| - } else { |
67 |
| - let root = src.join(name).join("src/lib.rs"); |
68 |
| - if root.exists() { |
69 |
| - sysroot.crates.alloc(SysrootCrateData { |
70 |
| - name: name.into(), |
71 |
| - root, |
72 |
| - deps: Vec::new(), |
73 |
| - }); |
74 |
| - } |
75 | 81 | }
|
76 | 82 | }
|
| 83 | + |
77 | 84 | if let Some(std) = sysroot.std() {
|
78 | 85 | for dep in STD_DEPS.trim().lines() {
|
79 | 86 | if let Some(dep) = sysroot.by_name(dep) {
|
80 | 87 | sysroot.crates[std].deps.push(dep)
|
81 | 88 | }
|
82 | 89 | }
|
83 | 90 | }
|
| 91 | + |
84 | 92 | if let Some(alloc) = sysroot.alloc() {
|
85 | 93 | if let Some(core) = sysroot.core() {
|
86 | 94 | sysroot.crates[alloc].deps.push(core);
|
87 | 95 | }
|
88 | 96 | }
|
89 |
| - Ok(sysroot) |
| 97 | + |
| 98 | + sysroot |
90 | 99 | }
|
91 | 100 |
|
92 | 101 | fn by_name(&self, name: &str) -> Option<SysrootCrate> {
|
93 |
| - self.crates.iter().find(|(_id, data)| data.name == name).map(|(id, _data)| id) |
| 102 | + let (id, _data) = self.crates.iter().find(|(_id, data)| data.name == name)?; |
| 103 | + Some(id) |
94 | 104 | }
|
95 | 105 | }
|
96 | 106 |
|
97 |
| -fn get_or_install_rust_src(cargo_toml: &AbsPath) -> Result<AbsPathBuf> { |
| 107 | +fn discover_sysroot_src_dir(current_dir: &AbsPath) -> Result<AbsPathBuf> { |
98 | 108 | if let Ok(path) = env::var("RUST_SRC_PATH") {
|
99 | 109 | let path = AbsPathBuf::try_from(path.as_str())
|
100 | 110 | .map_err(|path| format_err!("RUST_SRC_PATH must be absolute: {}", path.display()))?;
|
101 | 111 | return Ok(path);
|
102 | 112 | }
|
103 |
| - let current_dir = cargo_toml.parent().unwrap(); |
104 |
| - let mut rustc = Command::new(toolchain::rustc()); |
105 |
| - rustc.current_dir(current_dir).args(&["--print", "sysroot"]); |
106 |
| - let stdout = utf8_stdout(rustc)?; |
107 |
| - let sysroot_path = AbsPath::assert(Path::new(stdout.trim())); |
108 |
| - let mut src = get_rust_src(sysroot_path); |
109 |
| - if src.is_none() { |
110 |
| - let mut rustup = Command::new(toolchain::rustup()); |
111 |
| - rustup.current_dir(current_dir).args(&["component", "add", "rust-src"]); |
112 |
| - utf8_stdout(rustup)?; |
113 |
| - src = get_rust_src(sysroot_path); |
114 |
| - } |
115 |
| - match src { |
116 |
| - Some(r) => Ok(r), |
117 |
| - None => bail!( |
118 |
| - "can't load standard library from sysroot\n\ |
119 |
| - {}\n\ |
120 |
| - (discovered via `rustc --print sysroot`)\n\ |
121 |
| - try running `rustup component add rust-src` or set `RUST_SRC_PATH`", |
122 |
| - sysroot_path.display(), |
123 |
| - ), |
124 |
| - } |
| 113 | + |
| 114 | + let sysroot_path = { |
| 115 | + let mut rustc = Command::new(toolchain::rustc()); |
| 116 | + rustc.current_dir(current_dir).args(&["--print", "sysroot"]); |
| 117 | + let stdout = utf8_stdout(rustc)?; |
| 118 | + AbsPathBuf::assert(PathBuf::from(stdout)) |
| 119 | + }; |
| 120 | + |
| 121 | + get_rust_src(&sysroot_path) |
| 122 | + .or_else(|| { |
| 123 | + let mut rustup = Command::new(toolchain::rustup()); |
| 124 | + rustup.current_dir(current_dir).args(&["component", "add", "rust-src"]); |
| 125 | + utf8_stdout(rustup).ok()?; |
| 126 | + get_rust_src(&sysroot_path) |
| 127 | + }) |
| 128 | + .ok_or_else(|| { |
| 129 | + format_err!( |
| 130 | + "\ |
| 131 | +can't load standard library from sysroot |
| 132 | +{} |
| 133 | +(discovered via `rustc --print sysroot`) |
| 134 | +try running `rustup component add rust-src` or set `RUST_SRC_PATH`", |
| 135 | + sysroot_path.display(), |
| 136 | + ) |
| 137 | + }) |
125 | 138 | }
|
126 | 139 |
|
127 | 140 | fn get_rust_src(sysroot_path: &AbsPath) -> Option<AbsPathBuf> {
|
128 |
| - // try the new path first since the old one still exists |
129 |
| - let mut src_path = sysroot_path.join("lib/rustlib/src/rust/library"); |
130 |
| - if !src_path.exists() { |
131 |
| - // FIXME: remove this path when 1.47 comes out |
132 |
| - // https://github.com/rust-lang/rust/pull/73265 |
133 |
| - src_path = sysroot_path.join("lib/rustlib/src/rust/src"); |
134 |
| - } |
135 |
| - if src_path.exists() { |
136 |
| - Some(src_path) |
137 |
| - } else { |
138 |
| - None |
139 |
| - } |
| 141 | + // Try the new path first since the old one still exists. |
| 142 | + // |
| 143 | + // FIXME: remove `src` when 1.47 comes out |
| 144 | + // https://github.com/rust-lang/rust/pull/73265 |
| 145 | + let rust_src = sysroot_path.join("lib/rustlib/src/rust"); |
| 146 | + ["library", "src"].iter().map(|it| rust_src.join(it)).find(|it| it.exists()) |
140 | 147 | }
|
141 | 148 |
|
142 | 149 | impl SysrootCrateData {
|
|
0 commit comments