From 4a6e602c9419cc5ed464343b2373c7fe86fb89d6 Mon Sep 17 00:00:00 2001 From: Benjamin Bouvier Date: Thu, 11 Feb 2021 17:34:56 +0100 Subject: Allow automatically detect the rustc-src directory (fixes #3517). If the configured rustcSource is set to "discover", try to automatically detect a source from the sysroot rustc directory. --- crates/project_model/src/cargo_workspace.rs | 11 +++++++- crates/project_model/src/lib.rs | 4 +-- crates/project_model/src/sysroot.rs | 40 +++++++++++++++++++++-------- crates/project_model/src/workspace.rs | 13 +++++++++- 4 files changed, 54 insertions(+), 14 deletions(-) (limited to 'crates/project_model/src') diff --git a/crates/project_model/src/cargo_workspace.rs b/crates/project_model/src/cargo_workspace.rs index f47898b9b..1d8d34a0b 100644 --- a/crates/project_model/src/cargo_workspace.rs +++ b/crates/project_model/src/cargo_workspace.rs @@ -44,6 +44,15 @@ impl ops::Index for CargoWorkspace { } } +/// Describes how to set the rustc source directory. +#[derive(Clone, Debug, PartialEq, Eq)] +pub enum RustcSource { + /// Explicit path for the rustc source directory. + Path(AbsPathBuf), + /// Try to automatically detect where the rustc source directory is. + Discover, +} + #[derive(Default, Clone, Debug, PartialEq, Eq)] pub struct CargoConfig { /// Do not activate the `default` feature. @@ -64,7 +73,7 @@ pub struct CargoConfig { pub no_sysroot: bool, /// rustc private crate source - pub rustc_source: Option, + pub rustc_source: Option, } pub type Package = Idx; diff --git a/crates/project_model/src/lib.rs b/crates/project_model/src/lib.rs index d712095a6..a5b35ed95 100644 --- a/crates/project_model/src/lib.rs +++ b/crates/project_model/src/lib.rs @@ -21,8 +21,8 @@ use rustc_hash::FxHashSet; pub use crate::{ build_data::{BuildDataCollector, BuildDataResult}, cargo_workspace::{ - CargoConfig, CargoWorkspace, Package, PackageData, PackageDependency, Target, TargetData, - TargetKind, + CargoConfig, CargoWorkspace, Package, PackageData, PackageDependency, RustcSource, Target, + TargetData, TargetKind, }, project_json::{ProjectJson, ProjectJsonData}, sysroot::Sysroot, diff --git a/crates/project_model/src/sysroot.rs b/crates/project_model/src/sysroot.rs index ff44dae4a..3b0ff506d 100644 --- a/crates/project_model/src/sysroot.rs +++ b/crates/project_model/src/sysroot.rs @@ -51,11 +51,18 @@ impl Sysroot { pub fn discover(cargo_toml: &AbsPath) -> Result { log::debug!("Discovering sysroot for {}", cargo_toml.display()); let current_dir = cargo_toml.parent().unwrap(); - let sysroot_src_dir = discover_sysroot_src_dir(current_dir)?; + let sysroot_dir = discover_sysroot_dir(current_dir)?; + let sysroot_src_dir = discover_sysroot_src_dir(&sysroot_dir, current_dir)?; let res = Sysroot::load(&sysroot_src_dir)?; Ok(res) } + pub fn discover_rustc(cargo_toml: &AbsPath) -> Option { + log::debug!("Discovering rustc source for {}", cargo_toml.display()); + let current_dir = cargo_toml.parent().unwrap(); + discover_sysroot_dir(current_dir).ok().and_then(|sysroot_dir| get_rustc_src(&sysroot_dir)) + } + pub fn load(sysroot_src_dir: &AbsPath) -> Result { let mut sysroot = Sysroot { crates: Arena::default() }; @@ -110,7 +117,18 @@ impl Sysroot { } } -fn discover_sysroot_src_dir(current_dir: &AbsPath) -> Result { +fn discover_sysroot_dir(current_dir: &AbsPath) -> Result { + let mut rustc = Command::new(toolchain::rustc()); + rustc.current_dir(current_dir).args(&["--print", "sysroot"]); + log::debug!("Discovering sysroot by {:?}", rustc); + let stdout = utf8_stdout(rustc)?; + Ok(AbsPathBuf::assert(PathBuf::from(stdout))) +} + +fn discover_sysroot_src_dir( + sysroot_path: &AbsPathBuf, + current_dir: &AbsPath, +) -> Result { if let Ok(path) = env::var("RUST_SRC_PATH") { let path = AbsPathBuf::try_from(path.as_str()) .map_err(|path| format_err!("RUST_SRC_PATH must be absolute: {}", path.display()))?; @@ -122,14 +140,6 @@ fn discover_sysroot_src_dir(current_dir: &AbsPath) -> Result { log::debug!("RUST_SRC_PATH is set, but is invalid (no core: {:?}), ignoring", core); } - let sysroot_path = { - let mut rustc = Command::new(toolchain::rustc()); - rustc.current_dir(current_dir).args(&["--print", "sysroot"]); - log::debug!("Discovering sysroot by {:?}", rustc); - let stdout = utf8_stdout(rustc)?; - AbsPathBuf::assert(PathBuf::from(stdout)) - }; - get_rust_src(&sysroot_path) .or_else(|| { let mut rustup = Command::new(toolchain::rustup()); @@ -149,6 +159,16 @@ try installing the Rust source the same way you installed rustc", }) } +fn get_rustc_src(sysroot_path: &AbsPath) -> Option { + let rustc_src = sysroot_path.join("lib/rustlib/rustc-src/rust/compiler/rustc/Cargo.toml"); + log::debug!("Checking for rustc source code: {}", rustc_src.display()); + if rustc_src.exists() { + Some(rustc_src) + } else { + None + } +} + fn get_rust_src(sysroot_path: &AbsPath) -> Option { // Try the new path first since the old one still exists. let rust_src = sysroot_path.join("lib/rustlib/src/rust"); diff --git a/crates/project_model/src/workspace.rs b/crates/project_model/src/workspace.rs index c30861976..0220efdb4 100644 --- a/crates/project_model/src/workspace.rs +++ b/crates/project_model/src/workspace.rs @@ -114,6 +114,7 @@ impl ProjectWorkspace { cargo_version ) })?; + let sysroot = if config.no_sysroot { Sysroot::default() } else { @@ -125,7 +126,17 @@ impl ProjectWorkspace { })? }; - let rustc = if let Some(rustc_dir) = &config.rustc_source { + let rustc_dir = if let Some(rustc_source) = &config.rustc_source { + use cargo_workspace::RustcSource; + match rustc_source { + RustcSource::Path(path) => Some(path.clone()), + RustcSource::Discover => Sysroot::discover_rustc(&cargo_toml), + } + } else { + None + }; + + let rustc = if let Some(rustc_dir) = rustc_dir { Some( CargoWorkspace::from_cargo_metadata(&rustc_dir, config, progress) .with_context(|| { -- cgit v1.2.3