diff options
Diffstat (limited to 'crates/project_model/src/workspace.rs')
-rw-r--r-- | crates/project_model/src/workspace.rs | 79 |
1 files changed, 61 insertions, 18 deletions
diff --git a/crates/project_model/src/workspace.rs b/crates/project_model/src/workspace.rs index 8e0481ae9..0220efdb4 100644 --- a/crates/project_model/src/workspace.rs +++ b/crates/project_model/src/workspace.rs | |||
@@ -16,8 +16,13 @@ use proc_macro_api::ProcMacroClient; | |||
16 | use rustc_hash::{FxHashMap, FxHashSet}; | 16 | use rustc_hash::{FxHashMap, FxHashSet}; |
17 | 17 | ||
18 | use crate::{ | 18 | use crate::{ |
19 | cargo_workspace, cfg_flag::CfgFlag, rustc_cfg, sysroot::SysrootCrate, utf8_stdout, CargoConfig, | 19 | build_data::{BuildData, BuildDataMap, BuildDataResult}, |
20 | CargoWorkspace, ProjectJson, ProjectManifest, Sysroot, TargetKind, | 20 | cargo_workspace, |
21 | cfg_flag::CfgFlag, | ||
22 | rustc_cfg, | ||
23 | sysroot::SysrootCrate, | ||
24 | utf8_stdout, BuildDataCollector, CargoConfig, CargoWorkspace, ProjectJson, ProjectManifest, | ||
25 | Sysroot, TargetKind, | ||
21 | }; | 26 | }; |
22 | 27 | ||
23 | /// `PackageRoot` describes a package root folder. | 28 | /// `PackageRoot` describes a package root folder. |
@@ -51,6 +56,7 @@ pub enum ProjectWorkspace { | |||
51 | 56 | ||
52 | impl fmt::Debug for ProjectWorkspace { | 57 | impl fmt::Debug for ProjectWorkspace { |
53 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { | 58 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
59 | // Make sure this isn't too verbose. | ||
54 | match self { | 60 | match self { |
55 | ProjectWorkspace::Cargo { cargo, sysroot, rustc, rustc_cfg } => f | 61 | ProjectWorkspace::Cargo { cargo, sysroot, rustc, rustc_cfg } => f |
56 | .debug_struct("Cargo") | 62 | .debug_struct("Cargo") |
@@ -60,7 +66,7 @@ impl fmt::Debug for ProjectWorkspace { | |||
60 | "n_rustc_compiler_crates", | 66 | "n_rustc_compiler_crates", |
61 | &rustc.as_ref().map_or(0, |rc| rc.packages().len()), | 67 | &rustc.as_ref().map_or(0, |rc| rc.packages().len()), |
62 | ) | 68 | ) |
63 | .field("rustc_cfg", rustc_cfg) | 69 | .field("n_rustc_cfg", &rustc_cfg.len()) |
64 | .finish(), | 70 | .finish(), |
65 | ProjectWorkspace::Json { project, sysroot, rustc_cfg } => { | 71 | ProjectWorkspace::Json { project, sysroot, rustc_cfg } => { |
66 | let mut debug_struct = f.debug_struct("Json"); | 72 | let mut debug_struct = f.debug_struct("Json"); |
@@ -68,7 +74,7 @@ impl fmt::Debug for ProjectWorkspace { | |||
68 | if let Some(sysroot) = sysroot { | 74 | if let Some(sysroot) = sysroot { |
69 | debug_struct.field("n_sysroot_crates", &sysroot.crates().len()); | 75 | debug_struct.field("n_sysroot_crates", &sysroot.crates().len()); |
70 | } | 76 | } |
71 | debug_struct.field("rustc_cfg", rustc_cfg); | 77 | debug_struct.field("n_rustc_cfg", &rustc_cfg.len()); |
72 | debug_struct.finish() | 78 | debug_struct.finish() |
73 | } | 79 | } |
74 | } | 80 | } |
@@ -108,6 +114,7 @@ impl ProjectWorkspace { | |||
108 | cargo_version | 114 | cargo_version |
109 | ) | 115 | ) |
110 | })?; | 116 | })?; |
117 | |||
111 | let sysroot = if config.no_sysroot { | 118 | let sysroot = if config.no_sysroot { |
112 | Sysroot::default() | 119 | Sysroot::default() |
113 | } else { | 120 | } else { |
@@ -119,7 +126,17 @@ impl ProjectWorkspace { | |||
119 | })? | 126 | })? |
120 | }; | 127 | }; |
121 | 128 | ||
122 | let rustc = if let Some(rustc_dir) = &config.rustc_source { | 129 | let rustc_dir = if let Some(rustc_source) = &config.rustc_source { |
130 | use cargo_workspace::RustcSource; | ||
131 | match rustc_source { | ||
132 | RustcSource::Path(path) => Some(path.clone()), | ||
133 | RustcSource::Discover => Sysroot::discover_rustc(&cargo_toml), | ||
134 | } | ||
135 | } else { | ||
136 | None | ||
137 | }; | ||
138 | |||
139 | let rustc = if let Some(rustc_dir) = rustc_dir { | ||
123 | Some( | 140 | Some( |
124 | CargoWorkspace::from_cargo_metadata(&rustc_dir, config, progress) | 141 | CargoWorkspace::from_cargo_metadata(&rustc_dir, config, progress) |
125 | .with_context(|| { | 142 | .with_context(|| { |
@@ -152,7 +169,7 @@ impl ProjectWorkspace { | |||
152 | /// Returns the roots for the current `ProjectWorkspace` | 169 | /// Returns the roots for the current `ProjectWorkspace` |
153 | /// The return type contains the path and whether or not | 170 | /// The return type contains the path and whether or not |
154 | /// the root is a member of the current workspace | 171 | /// the root is a member of the current workspace |
155 | pub fn to_roots(&self) -> Vec<PackageRoot> { | 172 | pub fn to_roots(&self, build_data: Option<&BuildDataResult>) -> Vec<PackageRoot> { |
156 | match self { | 173 | match self { |
157 | ProjectWorkspace::Json { project, sysroot, rustc_cfg: _ } => project | 174 | ProjectWorkspace::Json { project, sysroot, rustc_cfg: _ } => project |
158 | .crates() | 175 | .crates() |
@@ -178,7 +195,12 @@ impl ProjectWorkspace { | |||
178 | let pkg_root = cargo[pkg].root().to_path_buf(); | 195 | let pkg_root = cargo[pkg].root().to_path_buf(); |
179 | 196 | ||
180 | let mut include = vec![pkg_root.clone()]; | 197 | let mut include = vec![pkg_root.clone()]; |
181 | include.extend(cargo[pkg].out_dir.clone()); | 198 | include.extend( |
199 | build_data | ||
200 | .and_then(|it| it.get(cargo.workspace_root())) | ||
201 | .and_then(|map| map.get(&cargo[pkg].id)) | ||
202 | .and_then(|it| it.out_dir.clone()), | ||
203 | ); | ||
182 | 204 | ||
183 | let mut exclude = vec![pkg_root.join(".git")]; | 205 | let mut exclude = vec![pkg_root.join(".git")]; |
184 | if is_member { | 206 | if is_member { |
@@ -218,6 +240,7 @@ impl ProjectWorkspace { | |||
218 | 240 | ||
219 | pub fn to_crate_graph( | 241 | pub fn to_crate_graph( |
220 | &self, | 242 | &self, |
243 | build_data: Option<&BuildDataResult>, | ||
221 | proc_macro_client: Option<&ProcMacroClient>, | 244 | proc_macro_client: Option<&ProcMacroClient>, |
222 | load: &mut dyn FnMut(&AbsPath) -> Option<FileId>, | 245 | load: &mut dyn FnMut(&AbsPath) -> Option<FileId>, |
223 | ) -> CrateGraph { | 246 | ) -> CrateGraph { |
@@ -240,8 +263,10 @@ impl ProjectWorkspace { | |||
240 | &proc_macro_loader, | 263 | &proc_macro_loader, |
241 | load, | 264 | load, |
242 | cargo, | 265 | cargo, |
266 | build_data.and_then(|it| it.get(cargo.workspace_root())), | ||
243 | sysroot, | 267 | sysroot, |
244 | rustc, | 268 | rustc, |
269 | rustc.as_ref().zip(build_data).and_then(|(it, map)| map.get(it.workspace_root())), | ||
245 | ), | 270 | ), |
246 | }; | 271 | }; |
247 | if crate_graph.patch_cfg_if() { | 272 | if crate_graph.patch_cfg_if() { |
@@ -251,6 +276,18 @@ impl ProjectWorkspace { | |||
251 | } | 276 | } |
252 | crate_graph | 277 | crate_graph |
253 | } | 278 | } |
279 | |||
280 | pub fn collect_build_data_configs(&self, collector: &mut BuildDataCollector) { | ||
281 | match self { | ||
282 | ProjectWorkspace::Cargo { cargo, rustc, .. } => { | ||
283 | collector.add_config(&cargo.workspace_root(), cargo.build_data_config().clone()); | ||
284 | if let Some(rustc) = rustc { | ||
285 | collector.add_config(rustc.workspace_root(), rustc.build_data_config().clone()); | ||
286 | } | ||
287 | } | ||
288 | _ => {} | ||
289 | } | ||
290 | } | ||
254 | } | 291 | } |
255 | 292 | ||
256 | fn project_json_to_crate_graph( | 293 | fn project_json_to_crate_graph( |
@@ -323,8 +360,10 @@ fn cargo_to_crate_graph( | |||
323 | proc_macro_loader: &dyn Fn(&Path) -> Vec<ProcMacro>, | 360 | proc_macro_loader: &dyn Fn(&Path) -> Vec<ProcMacro>, |
324 | load: &mut dyn FnMut(&AbsPath) -> Option<FileId>, | 361 | load: &mut dyn FnMut(&AbsPath) -> Option<FileId>, |
325 | cargo: &CargoWorkspace, | 362 | cargo: &CargoWorkspace, |
363 | build_data_map: Option<&BuildDataMap>, | ||
326 | sysroot: &Sysroot, | 364 | sysroot: &Sysroot, |
327 | rustc: &Option<CargoWorkspace>, | 365 | rustc: &Option<CargoWorkspace>, |
366 | rustc_build_data_map: Option<&BuildDataMap>, | ||
328 | ) -> CrateGraph { | 367 | ) -> CrateGraph { |
329 | let _p = profile::span("cargo_to_crate_graph"); | 368 | let _p = profile::span("cargo_to_crate_graph"); |
330 | let mut crate_graph = CrateGraph::default(); | 369 | let mut crate_graph = CrateGraph::default(); |
@@ -350,6 +389,7 @@ fn cargo_to_crate_graph( | |||
350 | let crate_id = add_target_crate_root( | 389 | let crate_id = add_target_crate_root( |
351 | &mut crate_graph, | 390 | &mut crate_graph, |
352 | &cargo[pkg], | 391 | &cargo[pkg], |
392 | build_data_map.and_then(|it| it.get(&cargo[pkg].id)), | ||
353 | &cfg_options, | 393 | &cfg_options, |
354 | proc_macro_loader, | 394 | proc_macro_loader, |
355 | file_id, | 395 | file_id, |
@@ -426,6 +466,7 @@ fn cargo_to_crate_graph( | |||
426 | let crate_id = add_target_crate_root( | 466 | let crate_id = add_target_crate_root( |
427 | &mut crate_graph, | 467 | &mut crate_graph, |
428 | &rustc_workspace[pkg], | 468 | &rustc_workspace[pkg], |
469 | rustc_build_data_map.and_then(|it| it.get(&rustc_workspace[pkg].id)), | ||
429 | &cfg_options, | 470 | &cfg_options, |
430 | proc_macro_loader, | 471 | proc_macro_loader, |
431 | file_id, | 472 | file_id, |
@@ -474,6 +515,7 @@ fn cargo_to_crate_graph( | |||
474 | fn add_target_crate_root( | 515 | fn add_target_crate_root( |
475 | crate_graph: &mut CrateGraph, | 516 | crate_graph: &mut CrateGraph, |
476 | pkg: &cargo_workspace::PackageData, | 517 | pkg: &cargo_workspace::PackageData, |
518 | build_data: Option<&BuildData>, | ||
477 | cfg_options: &CfgOptions, | 519 | cfg_options: &CfgOptions, |
478 | proc_macro_loader: &dyn Fn(&Path) -> Vec<ProcMacro>, | 520 | proc_macro_loader: &dyn Fn(&Path) -> Vec<ProcMacro>, |
479 | file_id: FileId, | 521 | file_id: FileId, |
@@ -481,26 +523,27 @@ fn add_target_crate_root( | |||
481 | let edition = pkg.edition; | 523 | let edition = pkg.edition; |
482 | let cfg_options = { | 524 | let cfg_options = { |
483 | let mut opts = cfg_options.clone(); | 525 | let mut opts = cfg_options.clone(); |
484 | for feature in pkg.features.iter() { | 526 | for feature in pkg.active_features.iter() { |
485 | opts.insert_key_value("feature".into(), feature.into()); | 527 | opts.insert_key_value("feature".into(), feature.into()); |
486 | } | 528 | } |
487 | opts.extend(pkg.cfgs.iter().cloned()); | 529 | if let Some(cfgs) = build_data.as_ref().map(|it| &it.cfgs) { |
530 | opts.extend(cfgs.iter().cloned()); | ||
531 | } | ||
488 | opts | 532 | opts |
489 | }; | 533 | }; |
490 | 534 | ||
491 | let mut env = Env::default(); | 535 | let mut env = Env::default(); |
492 | for (k, v) in &pkg.envs { | 536 | if let Some(envs) = build_data.map(|it| &it.envs) { |
493 | env.set(k, v.clone()); | 537 | for (k, v) in envs { |
494 | } | 538 | env.set(k, v.clone()); |
495 | if let Some(out_dir) = &pkg.out_dir { | ||
496 | // NOTE: cargo and rustc seem to hide non-UTF-8 strings from env! and option_env!() | ||
497 | if let Some(out_dir) = out_dir.to_str().map(|s| s.to_owned()) { | ||
498 | env.set("OUT_DIR", out_dir); | ||
499 | } | 539 | } |
500 | } | 540 | } |
501 | 541 | ||
502 | let proc_macro = | 542 | let proc_macro = build_data |
503 | pkg.proc_macro_dylib_path.as_ref().map(|it| proc_macro_loader(&it)).unwrap_or_default(); | 543 | .as_ref() |
544 | .and_then(|it| it.proc_macro_dylib_path.as_ref()) | ||
545 | .map(|it| proc_macro_loader(&it)) | ||
546 | .unwrap_or_default(); | ||
504 | 547 | ||
505 | let display_name = CrateDisplayName::from_canonical_name(pkg.name.clone()); | 548 | let display_name = CrateDisplayName::from_canonical_name(pkg.name.clone()); |
506 | let crate_id = crate_graph.add_crate_root( | 549 | let crate_id = crate_graph.add_crate_root( |