diff --git a/crates/paths/src/lib.rs b/crates/paths/src/lib.rs index 22011cb33e..f09ad37e33 100644 --- a/crates/paths/src/lib.rs +++ b/crates/paths/src/lib.rs @@ -1,6 +1,7 @@ //! Thin wrappers around `std::path`, distinguishing between absolute and //! relative paths. use std::{ + borrow::Borrow, convert::{TryFrom, TryInto}, ops, path::{Component, Path, PathBuf}, @@ -35,6 +36,12 @@ impl AsRef for AbsPathBuf { } } +impl Borrow for AbsPathBuf { + fn borrow(&self) -> &AbsPath { + self.as_path() + } +} + impl TryFrom for AbsPathBuf { type Error = PathBuf; fn try_from(path_buf: PathBuf) -> Result { diff --git a/crates/project_model/src/build_data.rs b/crates/project_model/src/build_data.rs index c2c87b207b..fdf4b2d551 100644 --- a/crates/project_model/src/build_data.rs +++ b/crates/project_model/src/build_data.rs @@ -18,7 +18,7 @@ use stdx::JodChild; use crate::{cfg_flag::CfgFlag, CargoConfig}; #[derive(Debug, Clone, Default, PartialEq, Eq)] -pub(crate) struct BuildData { +pub(crate) struct PackageBuildData { /// List of config flags defined by this package's build script pub(crate) cfgs: Vec, /// List of cargo-related environment variables with their value @@ -32,6 +32,16 @@ pub(crate) struct BuildData { pub(crate) proc_macro_dylib_path: Option, } +#[derive(Debug, Default, PartialEq, Eq, Clone)] +pub(crate) struct WorkspaceBuildData { + per_package: FxHashMap, +} + +#[derive(Debug, Default, PartialEq, Eq, Clone)] +pub struct BuildDataResult { + per_workspace: FxHashMap, +} + #[derive(Clone, Debug)] pub(crate) struct BuildDataConfig { cargo_toml: AbsPathBuf, @@ -52,13 +62,6 @@ pub struct BuildDataCollector { configs: FxHashMap, } -#[derive(Debug, Default, PartialEq, Eq, Clone)] -pub struct BuildDataResult { - data: FxHashMap, -} - -pub(crate) type BuildDataMap = FxHashMap; - impl BuildDataCollector { pub(crate) fn add_config(&mut self, workspace_root: &AbsPath, config: BuildDataConfig) { self.configs.insert(workspace_root.to_path_buf(), config); @@ -67,7 +70,7 @@ impl BuildDataCollector { pub fn collect(&mut self, progress: &dyn Fn(String)) -> Result { let mut res = BuildDataResult::default(); for (path, config) in self.configs.iter() { - res.data.insert( + res.per_workspace.insert( path.clone(), collect_from_workspace( &config.cargo_toml, @@ -81,9 +84,15 @@ impl BuildDataCollector { } } +impl WorkspaceBuildData { + pub(crate) fn get(&self, package_id: &str) -> Option<&PackageBuildData> { + self.per_package.get(package_id) + } +} + impl BuildDataResult { - pub(crate) fn get(&self, root: &AbsPath) -> Option<&BuildDataMap> { - self.data.get(&root.to_path_buf()) + pub(crate) fn get(&self, workspace_root: &AbsPath) -> Option<&WorkspaceBuildData> { + self.per_workspace.get(workspace_root) } } @@ -102,7 +111,7 @@ fn collect_from_workspace( cargo_features: &CargoConfig, packages: &Vec, progress: &dyn Fn(String), -) -> Result { +) -> Result { let mut cmd = Command::new(toolchain::cargo()); cmd.args(&["check", "--workspace", "--message-format=json", "--manifest-path"]) .arg(cargo_toml.as_ref()); @@ -136,7 +145,7 @@ fn collect_from_workspace( let child_stdout = child.stdout.take().unwrap(); let stdout = BufReader::new(child_stdout); - let mut res = BuildDataMap::default(); + let mut res = WorkspaceBuildData::default(); for message in cargo_metadata::Message::parse_stream(stdout).flatten() { match message { Message::BuildScriptExecuted(BuildScript { @@ -154,16 +163,17 @@ fn collect_from_workspace( } acc }; - let res = res.entry(package_id.repr.clone()).or_default(); + let package_build_data = + res.per_package.entry(package_id.repr.clone()).or_default(); // cargo_metadata crate returns default (empty) path for // older cargos, which is not absolute, so work around that. if !out_dir.as_str().is_empty() { let out_dir = AbsPathBuf::assert(PathBuf::from(out_dir.into_os_string())); - res.out_dir = Some(out_dir); - res.cfgs = cfgs; + package_build_data.out_dir = Some(out_dir); + package_build_data.cfgs = cfgs; } - res.envs = env; + package_build_data.envs = env; } Message::CompilerArtifact(message) => { progress(format!("metadata {}", message.target.name)); @@ -173,8 +183,9 @@ fn collect_from_workspace( // Skip rmeta file if let Some(filename) = message.filenames.iter().find(|name| is_dylib(name)) { let filename = AbsPathBuf::assert(PathBuf::from(&filename)); - let res = res.entry(package_id.repr.clone()).or_default(); - res.proc_macro_dylib_path = Some(filename); + let package_build_data = + res.per_package.entry(package_id.repr.clone()).or_default(); + package_build_data.proc_macro_dylib_path = Some(filename); } } } @@ -188,12 +199,12 @@ fn collect_from_workspace( } for package in packages { - let build_data = res.entry(package.id.repr.clone()).or_default(); - inject_cargo_env(package, build_data); - if let Some(out_dir) = &build_data.out_dir { + let package_build_data = res.per_package.entry(package.id.repr.clone()).or_default(); + inject_cargo_env(package, package_build_data); + if let Some(out_dir) = &package_build_data.out_dir { // NOTE: cargo and rustc seem to hide non-UTF-8 strings from env! and option_env!() if let Some(out_dir) = out_dir.to_str().map(|s| s.to_owned()) { - build_data.envs.push(("OUT_DIR".to_string(), out_dir)); + package_build_data.envs.push(("OUT_DIR".to_string(), out_dir)); } } } @@ -212,7 +223,7 @@ fn is_dylib(path: &Utf8Path) -> bool { /// Recreates the compile-time environment variables that Cargo sets. /// /// Should be synced with -fn inject_cargo_env(package: &cargo_metadata::Package, build_data: &mut BuildData) { +fn inject_cargo_env(package: &cargo_metadata::Package, build_data: &mut PackageBuildData) { let env = &mut build_data.envs; // FIXME: Missing variables: diff --git a/crates/project_model/src/workspace.rs b/crates/project_model/src/workspace.rs index 1b53fcc30a..2fcd0f8fac 100644 --- a/crates/project_model/src/workspace.rs +++ b/crates/project_model/src/workspace.rs @@ -12,7 +12,7 @@ use proc_macro_api::ProcMacroClient; use rustc_hash::{FxHashMap, FxHashSet}; use crate::{ - build_data::{BuildData, BuildDataMap, BuildDataResult}, + build_data::{BuildDataResult, PackageBuildData, WorkspaceBuildData}, cargo_workspace, cfg_flag::CfgFlag, rustc_cfg, @@ -354,10 +354,10 @@ fn cargo_to_crate_graph( proc_macro_loader: &dyn Fn(&Path) -> Vec, load: &mut dyn FnMut(&AbsPath) -> Option, cargo: &CargoWorkspace, - build_data_map: Option<&BuildDataMap>, + build_data_map: Option<&WorkspaceBuildData>, sysroot: &Sysroot, rustc: &Option, - rustc_build_data_map: Option<&BuildDataMap>, + rustc_build_data_map: Option<&WorkspaceBuildData>, ) -> CrateGraph { let _p = profile::span("cargo_to_crate_graph"); let mut crate_graph = CrateGraph::default(); @@ -464,7 +464,7 @@ fn handle_rustc_crates( rustc_workspace: &CargoWorkspace, load: &mut dyn FnMut(&AbsPath) -> Option, crate_graph: &mut CrateGraph, - rustc_build_data_map: Option<&FxHashMap>, + rustc_build_data_map: Option<&WorkspaceBuildData>, cfg_options: &CfgOptions, proc_macro_loader: &dyn Fn(&Path) -> Vec, pkg_to_lib_crate: &mut FxHashMap, CrateId>, @@ -555,7 +555,7 @@ fn handle_rustc_crates( fn add_target_crate_root( crate_graph: &mut CrateGraph, pkg: &cargo_workspace::PackageData, - build_data: Option<&BuildData>, + build_data: Option<&PackageBuildData>, cfg_options: &CfgOptions, proc_macro_loader: &dyn Fn(&Path) -> Vec, file_id: FileId,