aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorbors[bot] <26634292+bors[bot]@users.noreply.github.com>2020-02-17 23:01:54 +0000
committerGitHub <[email protected]>2020-02-17 23:01:54 +0000
commit585eef1d8c79e24b7788363cf3a5bc7c9c3bc963 (patch)
tree1f011539525108a10f36fdcde151d294c78db1c0
parent326556b09078a398e641dd221ab870ee0fe47f68 (diff)
parente29dbdb139fb3a35902b4b3d11a92d45861d210b (diff)
Merge #3206
3206: Install rust-src when it is not found r=SomeoneToIgnore a=SomeoneToIgnore Closes https://github.com/rust-analyzer/rust-analyzer/issues/2858 Looks like there's no RUSTUP env variable, so it adds one more thing to solve in https://github.com/rust-analyzer/rust-analyzer/issues/3154 Co-authored-by: Kirill Bulatov <[email protected]>
-rw-r--r--crates/ra_project_model/src/sysroot.rs72
-rw-r--r--docs/user/readme.adoc4
2 files changed, 47 insertions, 29 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 {
diff --git a/docs/user/readme.adoc b/docs/user/readme.adoc
index 57a8cbe31..8780a2995 100644
--- a/docs/user/readme.adoc
+++ b/docs/user/readme.adoc
@@ -20,7 +20,9 @@ In theory, one should be able to just install the server binary and have it auto
20We are not there yet, so some editor specific setup is required. 20We are not there yet, so some editor specific setup is required.
21 21
22Additionally, rust-analyzer needs sources of the standard library. 22Additionally, rust-analyzer needs sources of the standard library.
23This commands adds them: 23If the source code is not present, rust-analyzer will attempt to install it automatically.
24
25To add the sources manually, run the following command:
24 26
25```bash 27```bash
26$ rustup component add rust-src 28$ rustup component add rust-src