aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_project_model/src/sysroot.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_project_model/src/sysroot.rs')
-rw-r--r--crates/ra_project_model/src/sysroot.rs72
1 files changed, 44 insertions, 28 deletions
diff --git a/crates/ra_project_model/src/sysroot.rs b/crates/ra_project_model/src/sysroot.rs
index 7b9cc899c..db779a2d2 100644
--- a/crates/ra_project_model/src/sysroot.rs
+++ b/crates/ra_project_model/src/sysroot.rs
@@ -1,10 +1,10 @@
1//! FIXME: write short doc here 1//! FIXME: write short doc here
2 2
3use anyhow::{anyhow, bail, Context, Result}; 3use anyhow::{bail, Context, Result};
4use std::{ 4use std::{
5 env, 5 env,
6 path::{Path, PathBuf}, 6 path::{Path, PathBuf},
7 process::Command, 7 process::{Command, Output},
8}; 8};
9 9
10use ra_arena::{impl_arena_id, Arena, RawId}; 10use ra_arena::{impl_arena_id, Arena, RawId};
@@ -47,18 +47,7 @@ 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 src = try_find_src_path(cargo_toml)?; 50 let src = get_or_install_rust_src(cargo_toml)?;
51
52 if !src.exists() {
53 Err(anyhow!(
54 "can't load standard library from sysroot\n\
55 {}\n\
56 (discovered via `rustc --print sysroot`)\n\
57 try running `rustup component add rust-src` or set `RUST_SRC_PATH`",
58 src.display(),
59 ))?;
60 }
61
62 let mut sysroot = Sysroot { crates: Arena::default() }; 51 let mut sysroot = Sysroot { crates: Arena::default() };
63 for name in SYSROOT_CRATES.trim().lines() { 52 for name in SYSROOT_CRATES.trim().lines() {
64 let root = src.join(format!("lib{}", name)).join("lib.rs"); 53 let root = src.join(format!("lib{}", name)).join("lib.rs");
@@ -90,27 +79,54 @@ impl Sysroot {
90 } 79 }
91} 80}
92 81
93fn try_find_src_path(cargo_toml: &Path) -> Result<PathBuf> { 82fn create_command_text(program: &str, args: &[&str]) -> String {
94 if let Ok(path) = env::var("RUST_SRC_PATH") { 83 format!("{} {}", program, args.join(" "))
95 return Ok(path.into()); 84}
96 }
97 85
98 let rustc_output = Command::new("rustc") 86fn run_command_in_cargo_dir(cargo_toml: &Path, program: &str, args: &[&str]) -> Result<Output> {
87 let output = Command::new(program)
99 .current_dir(cargo_toml.parent().unwrap()) 88 .current_dir(cargo_toml.parent().unwrap())
100 .args(&["--print", "sysroot"]) 89 .args(args)
101 .output() 90 .output()
102 .context("rustc --print sysroot failed")?; 91 .context(format!("{} failed", create_command_text(program, args)))?;
103 if !rustc_output.status.success() { 92 if !output.status.success() {
104 match rustc_output.status.code() { 93 match output.status.code() {
105 Some(code) => { 94 Some(code) => bail!(
106 bail!("failed to locate sysroot: rustc --print sysroot exited with code {}", code) 95 "failed to run the command: '{}' exited with code {}",
107 } 96 create_command_text(program, args),
108 None => bail!("failed to locate sysroot: rustc --print sysroot terminated by signal"), 97 code
98 ),
99 None => bail!(
100 "failed to run the command: '{}' terminated by signal",
101 create_command_text(program, args)
102 ),
109 }; 103 };
110 } 104 }
105 Ok(output)
106}
107
108fn get_or_install_rust_src(cargo_toml: &Path) -> Result<PathBuf> {
109 if let Ok(path) = env::var("RUST_SRC_PATH") {
110 return Ok(path.into());
111 }
112 let rustc_output = run_command_in_cargo_dir(cargo_toml, "rustc", &["--print", "sysroot"])?;
111 let stdout = String::from_utf8(rustc_output.stdout)?; 113 let stdout = String::from_utf8(rustc_output.stdout)?;
112 let sysroot_path = Path::new(stdout.trim()); 114 let sysroot_path = Path::new(stdout.trim());
113 Ok(sysroot_path.join("lib/rustlib/src/rust/src")) 115 let src_path = sysroot_path.join("lib/rustlib/src/rust/src");
116
117 if !src_path.exists() {
118 run_command_in_cargo_dir(cargo_toml, "rustup", &["component", "add", "rust-src"])?;
119 }
120 if !src_path.exists() {
121 bail!(
122 "can't load standard library from sysroot\n\
123 {}\n\
124 (discovered via `rustc --print sysroot`)\n\
125 try running `rustup component add rust-src` or set `RUST_SRC_PATH`",
126 src_path.display(),
127 )
128 }
129 Ok(src_path)
114} 130}
115 131
116impl SysrootCrate { 132impl SysrootCrate {