diff options
-rw-r--r-- | crates/ra_project_model/src/sysroot.rs | 103 |
1 files changed, 56 insertions, 47 deletions
diff --git a/crates/ra_project_model/src/sysroot.rs b/crates/ra_project_model/src/sysroot.rs index 28756c7ca..43b062023 100644 --- a/crates/ra_project_model/src/sysroot.rs +++ b/crates/ra_project_model/src/sysroot.rs | |||
@@ -47,19 +47,16 @@ impl Sysroot { | |||
47 | } | 47 | } |
48 | 48 | ||
49 | pub fn discover(cargo_toml: &Path) -> Result<Sysroot> { | 49 | pub fn discover(cargo_toml: &Path) -> Result<Sysroot> { |
50 | let mut src = try_find_src_path(cargo_toml)?; | 50 | let src = get_or_install_rust_src(cargo_toml)?; |
51 | 51 | ||
52 | if !src.exists() { | 52 | if !src.exists() { |
53 | src = try_install_rust_src(cargo_toml)?; | 53 | Err(anyhow!( |
54 | if !src.exists() { | 54 | "can't load standard library from sysroot\n\ |
55 | Err(anyhow!( | 55 | {}\n\ |
56 | "can't load standard library from sysroot\n\ | 56 | (discovered via `rustc --print sysroot`)\n\ |
57 | {}\n\ | 57 | try running `rustup component add rust-src` or set `RUST_SRC_PATH`", |
58 | (discovered via `rustc --print sysroot`)\n\ | 58 | src.display(), |
59 | try running `rustup component add rust-src` or set `RUST_SRC_PATH`", | 59 | ))?; |
60 | src.display(), | ||
61 | ))?; | ||
62 | } | ||
63 | } | 60 | } |
64 | 61 | ||
65 | let mut sysroot = Sysroot { crates: Arena::default() }; | 62 | let mut sysroot = Sysroot { crates: Arena::default() }; |
@@ -93,47 +90,59 @@ impl Sysroot { | |||
93 | } | 90 | } |
94 | } | 91 | } |
95 | 92 | ||
96 | fn try_find_src_path(cargo_toml: &Path) -> Result<PathBuf> { | 93 | fn get_or_install_rust_src(cargo_toml: &Path) -> Result<PathBuf> { |
97 | if let Ok(path) = env::var("RUST_SRC_PATH") { | 94 | fn try_find_src_path(cargo_toml: &Path) -> Result<PathBuf> { |
98 | return Ok(path.into()); | 95 | if let Ok(path) = env::var("RUST_SRC_PATH") { |
96 | return Ok(path.into()); | ||
97 | } | ||
98 | |||
99 | let rustc_output = Command::new("rustc") | ||
100 | .current_dir(cargo_toml.parent().unwrap()) | ||
101 | .args(&["--print", "sysroot"]) | ||
102 | .output() | ||
103 | .context("rustc --print sysroot failed")?; | ||
104 | if !rustc_output.status.success() { | ||
105 | match rustc_output.status.code() { | ||
106 | Some(code) => bail!( | ||
107 | "failed to locate sysroot: rustc --print sysroot exited with code {}", | ||
108 | code | ||
109 | ), | ||
110 | None => { | ||
111 | bail!("failed to locate sysroot: rustc --print sysroot terminated by signal") | ||
112 | } | ||
113 | }; | ||
114 | } | ||
115 | let stdout = String::from_utf8(rustc_output.stdout)?; | ||
116 | let sysroot_path = Path::new(stdout.trim()); | ||
117 | Ok(sysroot_path.join("lib/rustlib/src/rust/src")) | ||
99 | } | 118 | } |
100 | 119 | ||
101 | let rustc_output = Command::new("rustc") | 120 | fn try_install_rust_src(cargo_toml: &Path) -> Result<PathBuf> { |
102 | .current_dir(cargo_toml.parent().unwrap()) | 121 | let rustup_output = Command::new("rustup") |
103 | .args(&["--print", "sysroot"]) | 122 | .current_dir(cargo_toml.parent().unwrap()) |
104 | .output() | 123 | .args(&["component", "add", "rust-src"]) |
105 | .context("rustc --print sysroot failed")?; | 124 | .output() |
106 | if !rustc_output.status.success() { | 125 | .context("rustup component add rust-src failed")?; |
107 | match rustc_output.status.code() { | 126 | if !rustup_output.status.success() { |
108 | Some(code) => { | 127 | match rustup_output.status.code() { |
109 | bail!("failed to locate sysroot: rustc --print sysroot exited with code {}", code) | 128 | Some(code) => bail!( |
110 | } | 129 | "failed to install rust-src: rustup component add rust-src exited with code {}", |
111 | None => bail!("failed to locate sysroot: rustc --print sysroot terminated by signal"), | 130 | code |
112 | }; | 131 | ), |
132 | None => bail!( | ||
133 | "failed to install rust-src: rustup component add rust-src terminated by signal" | ||
134 | ), | ||
135 | }; | ||
136 | } | ||
137 | try_find_src_path(cargo_toml) | ||
113 | } | 138 | } |
114 | let stdout = String::from_utf8(rustc_output.stdout)?; | ||
115 | let sysroot_path = Path::new(stdout.trim()); | ||
116 | Ok(sysroot_path.join("lib/rustlib/src/rust/src")) | ||
117 | } | ||
118 | 139 | ||
119 | fn try_install_rust_src(cargo_toml: &Path) -> Result<PathBuf> { | 140 | let src = try_find_src_path(cargo_toml)?; |
120 | let rustup_output = Command::new("rustup") | 141 | if !src.exists() { |
121 | .current_dir(cargo_toml.parent().unwrap()) | 142 | try_install_rust_src(cargo_toml) |
122 | .args(&["component", "add", "rust-src"]) | 143 | } else { |
123 | .output() | 144 | Ok(src) |
124 | .context("rustup component add rust-src failed")?; | ||
125 | if !rustup_output.status.success() { | ||
126 | match rustup_output.status.code() { | ||
127 | Some(code) => bail!( | ||
128 | "failed to install rust-src: rustup component add rust-src exited with code {}", | ||
129 | code | ||
130 | ), | ||
131 | None => bail!( | ||
132 | "failed to install rust-src: rustup component add rust-src terminated by signal" | ||
133 | ), | ||
134 | }; | ||
135 | } | 145 | } |
136 | try_find_src_path(cargo_toml) | ||
137 | } | 146 | } |
138 | 147 | ||
139 | impl SysrootCrate { | 148 | impl SysrootCrate { |