diff options
Diffstat (limited to 'crates/project_model/src')
-rw-r--r-- | crates/project_model/src/lib.rs | 2 | ||||
-rw-r--r-- | crates/project_model/src/sysroot.rs | 113 |
2 files changed, 61 insertions, 54 deletions
diff --git a/crates/project_model/src/lib.rs b/crates/project_model/src/lib.rs index b601d7dc3..2d65fc076 100644 --- a/crates/project_model/src/lib.rs +++ b/crates/project_model/src/lib.rs | |||
@@ -561,5 +561,5 @@ fn utf8_stdout(mut cmd: Command) -> Result<String> { | |||
561 | } | 561 | } |
562 | } | 562 | } |
563 | let stdout = String::from_utf8(output.stdout)?; | 563 | let stdout = String::from_utf8(output.stdout)?; |
564 | Ok(stdout) | 564 | Ok(stdout.trim().to_string()) |
565 | } | 565 | } |
diff --git a/crates/project_model/src/sysroot.rs b/crates/project_model/src/sysroot.rs index 8239797b6..687e15337 100644 --- a/crates/project_model/src/sysroot.rs +++ b/crates/project_model/src/sysroot.rs | |||
@@ -1,8 +1,12 @@ | |||
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 | use arena::{Arena, Idx}; | 10 | use arena::{Arena, Idx}; |
7 | use paths::{AbsPath, AbsPathBuf}; | 11 | use paths::{AbsPath, AbsPathBuf}; |
8 | 12 | ||
@@ -51,29 +55,32 @@ impl Sysroot { | |||
51 | } | 55 | } |
52 | 56 | ||
53 | pub fn discover(cargo_toml: &AbsPath) -> Result<Sysroot> { | 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 | let mut sysroot = Sysroot { crates: Arena::default() }; | 65 | let mut sysroot = Sysroot { crates: Arena::default() }; |
66 | |||
56 | for name in SYSROOT_CRATES.trim().lines() { | 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 | // https://github.com/rust-lang/rust/pull/73265 | 69 | // https://github.com/rust-lang/rust/pull/73265 |
59 | let root = src.join(format!("lib{}", name)).join("lib.rs"); | 70 | let root = [format!("lib{}/lib.rs", name), format!("{}/src/lib.rs", name)] |
60 | if root.exists() { | 71 | .iter() |
72 | .map(|it| sysroot_src_dir.join(it)) | ||
73 | .find(|it| it.exists()); | ||
74 | |||
75 | if let Some(root) = root { | ||
61 | sysroot.crates.alloc(SysrootCrateData { | 76 | sysroot.crates.alloc(SysrootCrateData { |
62 | name: name.into(), | 77 | name: name.into(), |
63 | root, | 78 | root, |
64 | deps: Vec::new(), | 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 | if let Some(std) = sysroot.std() { | 84 | if let Some(std) = sysroot.std() { |
78 | for dep in STD_DEPS.trim().lines() { | 85 | for dep in STD_DEPS.trim().lines() { |
79 | if let Some(dep) = sysroot.by_name(dep) { | 86 | if let Some(dep) = sysroot.by_name(dep) { |
@@ -81,62 +88,62 @@ impl Sysroot { | |||
81 | } | 88 | } |
82 | } | 89 | } |
83 | } | 90 | } |
91 | |||
84 | if let Some(alloc) = sysroot.alloc() { | 92 | if let Some(alloc) = sysroot.alloc() { |
85 | if let Some(core) = sysroot.core() { | 93 | if let Some(core) = sysroot.core() { |
86 | sysroot.crates[alloc].deps.push(core); | 94 | sysroot.crates[alloc].deps.push(core); |
87 | } | 95 | } |
88 | } | 96 | } |
89 | Ok(sysroot) | 97 | |
98 | sysroot | ||
90 | } | 99 | } |
91 | 100 | ||
92 | fn by_name(&self, name: &str) -> Option<SysrootCrate> { | 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 | if let Ok(path) = env::var("RUST_SRC_PATH") { | 108 | if let Ok(path) = env::var("RUST_SRC_PATH") { |
99 | let path = AbsPathBuf::try_from(path.as_str()) | 109 | let path = AbsPathBuf::try_from(path.as_str()) |
100 | .map_err(|path| format_err!("RUST_SRC_PATH must be absolute: {}", path.display()))?; | 110 | .map_err(|path| format_err!("RUST_SRC_PATH must be absolute: {}", path.display()))?; |
101 | return Ok(path); | 111 | return Ok(path); |
102 | } | 112 | } |
103 | let current_dir = cargo_toml.parent().unwrap(); | 113 | |
104 | let mut rustc = Command::new(toolchain::rustc()); | 114 | let sysroot_path = { |
105 | rustc.current_dir(current_dir).args(&["--print", "sysroot"]); | 115 | let mut rustc = Command::new(toolchain::rustc()); |
106 | let stdout = utf8_stdout(rustc)?; | 116 | rustc.current_dir(current_dir).args(&["--print", "sysroot"]); |
107 | let sysroot_path = AbsPath::assert(Path::new(stdout.trim())); | 117 | let stdout = utf8_stdout(rustc)?; |
108 | let mut src = get_rust_src(sysroot_path); | 118 | AbsPathBuf::assert(PathBuf::from(stdout)) |
109 | if src.is_none() { | 119 | }; |
110 | let mut rustup = Command::new(toolchain::rustup()); | 120 | |
111 | rustup.current_dir(current_dir).args(&["component", "add", "rust-src"]); | 121 | get_rust_src(&sysroot_path) |
112 | utf8_stdout(rustup)?; | 122 | .or_else(|| { |
113 | src = get_rust_src(sysroot_path); | 123 | let mut rustup = Command::new(toolchain::rustup()); |
114 | } | 124 | rustup.current_dir(current_dir).args(&["component", "add", "rust-src"]); |
115 | match src { | 125 | utf8_stdout(rustup).ok()?; |
116 | Some(r) => Ok(r), | 126 | get_rust_src(&sysroot_path) |
117 | None => bail!( | 127 | }) |
118 | "can't load standard library from sysroot\n\ | 128 | .ok_or_else(|| { |
119 | {}\n\ | 129 | format_err!( |
120 | (discovered via `rustc --print sysroot`)\n\ | 130 | "\ |
121 | try running `rustup component add rust-src` or set `RUST_SRC_PATH`", | 131 | can't load standard library from sysroot |
122 | sysroot_path.display(), | 132 | {} |
123 | ), | 133 | (discovered via `rustc --print sysroot`) |
124 | } | 134 | try running `rustup component add rust-src` or set `RUST_SRC_PATH`", |
135 | sysroot_path.display(), | ||
136 | ) | ||
137 | }) | ||
125 | } | 138 | } |
126 | 139 | ||
127 | fn get_rust_src(sysroot_path: &AbsPath) -> Option<AbsPathBuf> { | 140 | fn get_rust_src(sysroot_path: &AbsPath) -> Option<AbsPathBuf> { |
128 | // try the new path first since the old one still exists | 141 | // Try the new path first since the old one still exists. |
129 | let mut src_path = sysroot_path.join("lib/rustlib/src/rust/library"); | 142 | // |
130 | if !src_path.exists() { | 143 | // FIXME: remove `src` when 1.47 comes out |
131 | // FIXME: remove this path when 1.47 comes out | 144 | // https://github.com/rust-lang/rust/pull/73265 |
132 | // https://github.com/rust-lang/rust/pull/73265 | 145 | let rust_src = sysroot_path.join("lib/rustlib/src/rust"); |
133 | src_path = sysroot_path.join("lib/rustlib/src/rust/src"); | 146 | ["library", "src"].iter().map(|it| rust_src.join(it)).find(|it| it.exists()) |
134 | } | ||
135 | if src_path.exists() { | ||
136 | Some(src_path) | ||
137 | } else { | ||
138 | None | ||
139 | } | ||
140 | } | 147 | } |
141 | 148 | ||
142 | impl SysrootCrateData { | 149 | impl SysrootCrateData { |