aboutsummaryrefslogtreecommitdiff
path: root/crates/project_model/src/lib.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/project_model/src/lib.rs')
-rw-r--r--crates/project_model/src/lib.rs245
1 files changed, 121 insertions, 124 deletions
diff --git a/crates/project_model/src/lib.rs b/crates/project_model/src/lib.rs
index 2d65fc076..2d91939ce 100644
--- a/crates/project_model/src/lib.rs
+++ b/crates/project_model/src/lib.rs
@@ -39,11 +39,18 @@ pub enum ProjectWorkspace {
39impl fmt::Debug for ProjectWorkspace { 39impl fmt::Debug for ProjectWorkspace {
40 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 40 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
41 match self { 41 match self {
42 ProjectWorkspace::Cargo { cargo, .. } => { 42 ProjectWorkspace::Cargo { cargo, sysroot } => f
43 f.debug_struct("Cargo").field("n_packages", &cargo.packages().len()).finish() 43 .debug_struct("Cargo")
44 } 44 .field("n_packages", &cargo.packages().len())
45 .field("n_sysroot_crates", &sysroot.crates().len())
46 .finish(),
45 ProjectWorkspace::Json { project } => { 47 ProjectWorkspace::Json { project } => {
46 f.debug_struct("Json").field("n_crates", &project.crates.len()).finish() 48 let mut debug_struct = f.debug_struct("Json");
49 debug_struct.field("n_crates", &project.n_crates());
50 if let Some(sysroot) = &project.sysroot {
51 debug_struct.field("n_sysroot_crates", &sysroot.crates().len());
52 }
53 debug_struct.finish()
47 } 54 }
48 } 55 }
49 } 56 }
@@ -202,15 +209,21 @@ impl ProjectWorkspace {
202 pub fn to_roots(&self) -> Vec<PackageRoot> { 209 pub fn to_roots(&self) -> Vec<PackageRoot> {
203 match self { 210 match self {
204 ProjectWorkspace::Json { project } => project 211 ProjectWorkspace::Json { project } => project
205 .crates 212 .crates()
206 .iter() 213 .map(|(_, krate)| PackageRoot {
207 .map(|krate| PackageRoot {
208 is_member: krate.is_workspace_member, 214 is_member: krate.is_workspace_member,
209 include: krate.include.clone(), 215 include: krate.include.clone(),
210 exclude: krate.exclude.clone(), 216 exclude: krate.exclude.clone(),
211 }) 217 })
212 .collect::<FxHashSet<_>>() 218 .collect::<FxHashSet<_>>()
213 .into_iter() 219 .into_iter()
220 .chain(project.sysroot.as_ref().into_iter().flat_map(|sysroot| {
221 sysroot.crates().map(move |krate| PackageRoot {
222 is_member: false,
223 include: vec![sysroot[krate].root_dir().to_path_buf()],
224 exclude: Vec::new(),
225 })
226 }))
214 .collect::<Vec<_>>(), 227 .collect::<Vec<_>>(),
215 ProjectWorkspace::Cargo { cargo, sysroot } => cargo 228 ProjectWorkspace::Cargo { cargo, sysroot } => cargo
216 .packages() 229 .packages()
@@ -243,9 +256,8 @@ impl ProjectWorkspace {
243 pub fn proc_macro_dylib_paths(&self) -> Vec<AbsPathBuf> { 256 pub fn proc_macro_dylib_paths(&self) -> Vec<AbsPathBuf> {
244 match self { 257 match self {
245 ProjectWorkspace::Json { project } => project 258 ProjectWorkspace::Json { project } => project
246 .crates 259 .crates()
247 .iter() 260 .filter_map(|(_, krate)| krate.proc_macro_dylib_path.as_ref())
248 .filter_map(|krate| krate.proc_macro_dylib_path.as_ref())
249 .cloned() 261 .cloned()
250 .collect(), 262 .collect(),
251 ProjectWorkspace::Cargo { cargo, sysroot: _sysroot } => cargo 263 ProjectWorkspace::Cargo { cargo, sysroot: _sysroot } => cargo
@@ -258,7 +270,7 @@ impl ProjectWorkspace {
258 270
259 pub fn n_packages(&self) -> usize { 271 pub fn n_packages(&self) -> usize {
260 match self { 272 match self {
261 ProjectWorkspace::Json { project, .. } => project.crates.len(), 273 ProjectWorkspace::Json { project, .. } => project.n_crates(),
262 ProjectWorkspace::Cargo { cargo, sysroot } => { 274 ProjectWorkspace::Cargo { cargo, sysroot } => {
263 cargo.packages().len() + sysroot.crates().len() 275 cargo.packages().len() + sysroot.crates().len()
264 } 276 }
@@ -274,12 +286,15 @@ impl ProjectWorkspace {
274 let mut crate_graph = CrateGraph::default(); 286 let mut crate_graph = CrateGraph::default();
275 match self { 287 match self {
276 ProjectWorkspace::Json { project } => { 288 ProjectWorkspace::Json { project } => {
289 let sysroot_dps = project
290 .sysroot
291 .as_ref()
292 .map(|sysroot| sysroot_to_crate_graph(&mut crate_graph, sysroot, target, load));
293
277 let mut cfg_cache: FxHashMap<Option<&str>, Vec<CfgFlag>> = FxHashMap::default(); 294 let mut cfg_cache: FxHashMap<Option<&str>, Vec<CfgFlag>> = FxHashMap::default();
278 let crates: FxHashMap<_, _> = project 295 let crates: FxHashMap<_, _> = project
279 .crates 296 .crates()
280 .iter() 297 .filter_map(|(crate_id, krate)| {
281 .enumerate()
282 .filter_map(|(seq_index, krate)| {
283 let file_path = &krate.root_module; 298 let file_path = &krate.root_module;
284 let file_id = load(&file_path)?; 299 let file_id = load(&file_path)?;
285 300
@@ -297,9 +312,8 @@ impl ProjectWorkspace {
297 let mut cfg_options = CfgOptions::default(); 312 let mut cfg_options = CfgOptions::default();
298 cfg_options.extend(target_cfgs.iter().chain(krate.cfg.iter()).cloned()); 313 cfg_options.extend(target_cfgs.iter().chain(krate.cfg.iter()).cloned());
299 314
300 // FIXME: No crate name in json definition such that we cannot add OUT_DIR to env
301 Some(( 315 Some((
302 CrateId(seq_index as u32), 316 crate_id,
303 crate_graph.add_crate_root( 317 crate_graph.add_crate_root(
304 file_id, 318 file_id,
305 krate.edition, 319 krate.edition,
@@ -313,67 +327,33 @@ impl ProjectWorkspace {
313 }) 327 })
314 .collect(); 328 .collect();
315 329
316 for (id, krate) in project.crates.iter().enumerate() { 330 for (from, krate) in project.crates() {
317 for dep in &krate.deps { 331 if let Some(&from) = crates.get(&from) {
318 let from_crate_id = CrateId(id as u32); 332 if let Some((public_deps, _proc_macro)) = &sysroot_dps {
319 let to_crate_id = dep.crate_id; 333 for (name, to) in public_deps.iter() {
320 if let (Some(&from), Some(&to)) = 334 if let Err(_) = crate_graph.add_dep(from, name.clone(), *to) {
321 (crates.get(&from_crate_id), crates.get(&to_crate_id)) 335 log::error!("cyclic dependency on {} for {:?}", name, from)
322 { 336 }
323 if crate_graph.add_dep(from, dep.name.clone(), to).is_err() {
324 log::error!(
325 "cyclic dependency {:?} -> {:?}",
326 from_crate_id,
327 to_crate_id
328 );
329 } 337 }
330 } 338 }
331 }
332 }
333 }
334 ProjectWorkspace::Cargo { cargo, sysroot } => {
335 let mut cfg_options = CfgOptions::default();
336 cfg_options.extend(get_rustc_cfg_options(target));
337
338 let sysroot_crates: FxHashMap<_, _> = sysroot
339 .crates()
340 .filter_map(|krate| {
341 let file_id = load(&sysroot[krate].root)?;
342
343 let env = Env::default();
344 let proc_macro = vec![];
345 let name = sysroot[krate].name.clone();
346 let crate_id = crate_graph.add_crate_root(
347 file_id,
348 Edition::Edition2018,
349 Some(name),
350 cfg_options.clone(),
351 env,
352 proc_macro,
353 );
354 Some((krate, crate_id))
355 })
356 .collect();
357 339
358 for from in sysroot.crates() { 340 for dep in &krate.deps {
359 for &to in sysroot[from].deps.iter() { 341 let to_crate_id = dep.crate_id;
360 let name = &sysroot[to].name; 342 if let Some(&to) = crates.get(&to_crate_id) {
361 if let (Some(&from), Some(&to)) = 343 if let Err(_) = crate_graph.add_dep(from, dep.name.clone(), to) {
362 (sysroot_crates.get(&from), sysroot_crates.get(&to)) 344 log::error!("cyclic dependency {:?} -> {:?}", from, to);
363 { 345 }
364 if crate_graph.add_dep(from, CrateName::new(name).unwrap(), to).is_err()
365 {
366 log::error!("cyclic dependency between sysroot crates")
367 } 346 }
368 } 347 }
369 } 348 }
370 } 349 }
350 }
351 ProjectWorkspace::Cargo { cargo, sysroot } => {
352 let (public_deps, libproc_macro) =
353 sysroot_to_crate_graph(&mut crate_graph, sysroot, target, load);
371 354
372 let libcore = sysroot.core().and_then(|it| sysroot_crates.get(&it).copied()); 355 let mut cfg_options = CfgOptions::default();
373 let liballoc = sysroot.alloc().and_then(|it| sysroot_crates.get(&it).copied()); 356 cfg_options.extend(get_rustc_cfg_options(target));
374 let libstd = sysroot.std().and_then(|it| sysroot_crates.get(&it).copied());
375 let libproc_macro =
376 sysroot.proc_macro().and_then(|it| sysroot_crates.get(&it).copied());
377 357
378 let mut pkg_to_lib_crate = FxHashMap::default(); 358 let mut pkg_to_lib_crate = FxHashMap::default();
379 let mut pkg_crates = FxHashMap::default(); 359 let mut pkg_crates = FxHashMap::default();
@@ -424,14 +404,11 @@ impl ProjectWorkspace {
424 } 404 }
425 if cargo[tgt].is_proc_macro { 405 if cargo[tgt].is_proc_macro {
426 if let Some(proc_macro) = libproc_macro { 406 if let Some(proc_macro) = libproc_macro {
427 if crate_graph 407 if let Err(_) = crate_graph.add_dep(
428 .add_dep( 408 crate_id,
429 crate_id, 409 CrateName::new("proc_macro").unwrap(),
430 CrateName::new("proc_macro").unwrap(), 410 proc_macro,
431 proc_macro, 411 ) {
432 )
433 .is_err()
434 {
435 log::error!( 412 log::error!(
436 "cyclic dependency on proc_macro for {}", 413 "cyclic dependency on proc_macro for {}",
437 &cargo[pkg].name 414 &cargo[pkg].name
@@ -447,50 +424,24 @@ impl ProjectWorkspace {
447 // Set deps to the core, std and to the lib target of the current package 424 // Set deps to the core, std and to the lib target of the current package
448 for &from in pkg_crates.get(&pkg).into_iter().flatten() { 425 for &from in pkg_crates.get(&pkg).into_iter().flatten() {
449 if let Some((to, name)) = lib_tgt.clone() { 426 if let Some((to, name)) = lib_tgt.clone() {
450 if to != from 427 // For root projects with dashes in their name,
451 && crate_graph 428 // cargo metadata does not do any normalization,
452 .add_dep( 429 // so we do it ourselves currently
453 from, 430 let name = CrateName::normalize_dashes(&name);
454 // For root projects with dashes in their name, 431 if to != from && crate_graph.add_dep(from, name, to).is_err() {
455 // cargo metadata does not do any normalization, 432 log::error!(
456 // so we do it ourselves currently 433 "cyclic dependency between targets of {}",
457 CrateName::normalize_dashes(&name), 434 &cargo[pkg].name
458 to, 435 )
459 )
460 .is_err()
461 {
462 {
463 log::error!(
464 "cyclic dependency between targets of {}",
465 &cargo[pkg].name
466 )
467 }
468 }
469 }
470 // core is added as a dependency before std in order to
471 // mimic rustcs dependency order
472 if let Some(core) = libcore {
473 if crate_graph
474 .add_dep(from, CrateName::new("core").unwrap(), core)
475 .is_err()
476 {
477 log::error!("cyclic dependency on core for {}", &cargo[pkg].name)
478 }
479 }
480 if let Some(alloc) = liballoc {
481 if crate_graph
482 .add_dep(from, CrateName::new("alloc").unwrap(), alloc)
483 .is_err()
484 {
485 log::error!("cyclic dependency on alloc for {}", &cargo[pkg].name)
486 } 436 }
487 } 437 }
488 if let Some(std) = libstd { 438 for (name, krate) in public_deps.iter() {
489 if crate_graph 439 if let Err(_) = crate_graph.add_dep(from, name.clone(), *krate) {
490 .add_dep(from, CrateName::new("std").unwrap(), std) 440 log::error!(
491 .is_err() 441 "cyclic dependency on {} for {}",
492 { 442 name,
493 log::error!("cyclic dependency on std for {}", &cargo[pkg].name) 443 &cargo[pkg].name
444 )
494 } 445 }
495 } 446 }
496 } 447 }
@@ -500,12 +451,10 @@ impl ProjectWorkspace {
500 // target of downstream. 451 // target of downstream.
501 for pkg in cargo.packages() { 452 for pkg in cargo.packages() {
502 for dep in cargo[pkg].dependencies.iter() { 453 for dep in cargo[pkg].dependencies.iter() {
454 let name = CrateName::new(&dep.name).unwrap();
503 if let Some(&to) = pkg_to_lib_crate.get(&dep.pkg) { 455 if let Some(&to) = pkg_to_lib_crate.get(&dep.pkg) {
504 for &from in pkg_crates.get(&pkg).into_iter().flatten() { 456 for &from in pkg_crates.get(&pkg).into_iter().flatten() {
505 if crate_graph 457 if let Err(_) = crate_graph.add_dep(from, name.clone(), to) {
506 .add_dep(from, CrateName::new(&dep.name).unwrap(), to)
507 .is_err()
508 {
509 log::error!( 458 log::error!(
510 "cyclic dependency {} -> {}", 459 "cyclic dependency {} -> {}",
511 &cargo[pkg].name, 460 &cargo[pkg].name,
@@ -563,3 +512,51 @@ fn utf8_stdout(mut cmd: Command) -> Result<String> {
563 let stdout = String::from_utf8(output.stdout)?; 512 let stdout = String::from_utf8(output.stdout)?;
564 Ok(stdout.trim().to_string()) 513 Ok(stdout.trim().to_string())
565} 514}
515
516fn sysroot_to_crate_graph(
517 crate_graph: &mut CrateGraph,
518 sysroot: &Sysroot,
519 target: Option<&str>,
520 load: &mut dyn FnMut(&AbsPath) -> Option<FileId>,
521) -> (Vec<(CrateName, CrateId)>, Option<CrateId>) {
522 let mut cfg_options = CfgOptions::default();
523 cfg_options.extend(get_rustc_cfg_options(target));
524 let sysroot_crates: FxHashMap<_, _> = sysroot
525 .crates()
526 .filter_map(|krate| {
527 let file_id = load(&sysroot[krate].root)?;
528
529 let env = Env::default();
530 let proc_macro = vec![];
531 let name = sysroot[krate].name.clone();
532 let crate_id = crate_graph.add_crate_root(
533 file_id,
534 Edition::Edition2018,
535 Some(name),
536 cfg_options.clone(),
537 env,
538 proc_macro,
539 );
540 Some((krate, crate_id))
541 })
542 .collect();
543
544 for from in sysroot.crates() {
545 for &to in sysroot[from].deps.iter() {
546 let name = CrateName::new(&sysroot[to].name).unwrap();
547 if let (Some(&from), Some(&to)) = (sysroot_crates.get(&from), sysroot_crates.get(&to)) {
548 if let Err(_) = crate_graph.add_dep(from, name, to) {
549 log::error!("cyclic dependency between sysroot crates")
550 }
551 }
552 }
553 }
554
555 let public_deps = sysroot
556 .public_deps()
557 .map(|(name, idx)| (CrateName::new(name).unwrap(), sysroot_crates[&idx]))
558 .collect::<Vec<_>>();
559
560 let libproc_macro = sysroot.proc_macro().and_then(|it| sysroot_crates.get(&it).copied());
561 (public_deps, libproc_macro)
562}