aboutsummaryrefslogtreecommitdiff
path: root/crates/project_model/src
diff options
context:
space:
mode:
Diffstat (limited to 'crates/project_model/src')
-rw-r--r--crates/project_model/src/lib.rs2
-rw-r--r--crates/project_model/src/sysroot.rs113
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
3use std::{convert::TryFrom, env, ops, path::Path, process::Command}; 7use std::{convert::TryFrom, env, ops, path::PathBuf, process::Command};
4 8
5use anyhow::{bail, format_err, Result}; 9use anyhow::{format_err, Result};
6use arena::{Arena, Idx}; 10use arena::{Arena, Idx};
7use paths::{AbsPath, AbsPathBuf}; 11use 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
97fn get_or_install_rust_src(cargo_toml: &AbsPath) -> Result<AbsPathBuf> { 107fn 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`", 131can't load standard library from sysroot
122 sysroot_path.display(), 132{}
123 ), 133(discovered via `rustc --print sysroot`)
124 } 134try running `rustup component add rust-src` or set `RUST_SRC_PATH`",
135 sysroot_path.display(),
136 )
137 })
125} 138}
126 139
127fn get_rust_src(sysroot_path: &AbsPath) -> Option<AbsPathBuf> { 140fn 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
142impl SysrootCrateData { 149impl SysrootCrateData {