aboutsummaryrefslogtreecommitdiff
path: root/crates/project_model
diff options
context:
space:
mode:
authorbors[bot] <26634292+bors[bot]@users.noreply.github.com>2021-05-12 14:22:23 +0100
committerGitHub <[email protected]>2021-05-12 14:22:23 +0100
commita5b55828365b602f0ed117c9f1cc2a9eddd42512 (patch)
tree92c544276f4556e02c434321f2e0407d54d68a02 /crates/project_model
parent9a431c26f4528e2649de0ca171a38c93e473c94e (diff)
parenta272cdfecdbbd95725d66b2452da3d379ef35d76 (diff)
Merge #8812
8812: fix: fix dependencies of build scripts r=jonas-schievink a=jonas-schievink Previously, we added a dependency for all targets in a package to the package's library target. This is correct for most targets, except build scripts, which run before the library crate is built. This PR removes the incorrect dependency on the library target. We also used to treat all dependencies the same, which led to build scripts being able to use regular dependencies as well as dev-dependencies. This is also fixed by this PR, and build scripts only depend on build-dependencies. Incorrect dependency graph: ![screenshot-2021-05-11-23:35:01](https://user-images.githubusercontent.com/1786438/117975228-c2066a80-b32e-11eb-8f01-1e3ea904a608.png) Fixed graph after this PR: ![screenshot-2021-05-12-14:29:31](https://user-images.githubusercontent.com/1786438/117975253-c9c60f00-b32e-11eb-8f6c-9e42d4e32468.png) Co-authored-by: Jonas Schievink <[email protected]>
Diffstat (limited to 'crates/project_model')
-rw-r--r--crates/project_model/src/cargo_workspace.rs34
-rw-r--r--crates/project_model/src/workspace.rs34
2 files changed, 56 insertions, 12 deletions
diff --git a/crates/project_model/src/cargo_workspace.rs b/crates/project_model/src/cargo_workspace.rs
index b18699b77..4a4996cf4 100644
--- a/crates/project_model/src/cargo_workspace.rs
+++ b/crates/project_model/src/cargo_workspace.rs
@@ -119,6 +119,32 @@ pub struct RustAnalyzerPackageMetaData {
119pub struct PackageDependency { 119pub struct PackageDependency {
120 pub pkg: Package, 120 pub pkg: Package,
121 pub name: String, 121 pub name: String,
122 pub kind: DepKind,
123}
124
125#[derive(Debug, Clone, Eq, PartialEq)]
126pub enum DepKind {
127 /// Available to the library, binary, and dev targets in the package (but not the build script).
128 Normal,
129 /// Available only to test and bench targets (and the library target, when built with `cfg(test)`).
130 Dev,
131 /// Available only to the build script target.
132 Build,
133}
134
135impl DepKind {
136 fn new(list: &[cargo_metadata::DepKindInfo]) -> Self {
137 for info in list {
138 match info.kind {
139 cargo_metadata::DependencyKind::Normal => return Self::Normal,
140 cargo_metadata::DependencyKind::Development => return Self::Dev,
141 cargo_metadata::DependencyKind::Build => return Self::Build,
142 cargo_metadata::DependencyKind::Unknown => continue,
143 }
144 }
145
146 Self::Normal
147 }
122} 148}
123 149
124/// Information associated with a package's target 150/// Information associated with a package's target
@@ -144,6 +170,7 @@ pub enum TargetKind {
144 Example, 170 Example,
145 Test, 171 Test,
146 Bench, 172 Bench,
173 BuildScript,
147 Other, 174 Other,
148} 175}
149 176
@@ -155,6 +182,7 @@ impl TargetKind {
155 "test" => TargetKind::Test, 182 "test" => TargetKind::Test,
156 "bench" => TargetKind::Bench, 183 "bench" => TargetKind::Bench,
157 "example" => TargetKind::Example, 184 "example" => TargetKind::Example,
185 "custom-build" => TargetKind::BuildScript,
158 "proc-macro" => TargetKind::Lib, 186 "proc-macro" => TargetKind::Lib,
159 _ if kind.contains("lib") => TargetKind::Lib, 187 _ if kind.contains("lib") => TargetKind::Lib,
160 _ => continue, 188 _ => continue,
@@ -301,7 +329,11 @@ impl CargoWorkspace {
301 continue; 329 continue;
302 } 330 }
303 }; 331 };
304 let dep = PackageDependency { name: dep_node.name, pkg }; 332 let dep = PackageDependency {
333 name: dep_node.name,
334 pkg,
335 kind: DepKind::new(&dep_node.dep_kinds),
336 };
305 packages[source].dependencies.push(dep); 337 packages[source].dependencies.push(dep);
306 } 338 }
307 packages[source].active_features.extend(node.features); 339 packages[source].active_features.extend(node.features);
diff --git a/crates/project_model/src/workspace.rs b/crates/project_model/src/workspace.rs
index 761fbb3ab..607e62ea5 100644
--- a/crates/project_model/src/workspace.rs
+++ b/crates/project_model/src/workspace.rs
@@ -6,6 +6,7 @@ use std::{collections::VecDeque, fmt, fs, path::Path, process::Command};
6 6
7use anyhow::{Context, Result}; 7use anyhow::{Context, Result};
8use base_db::{CrateDisplayName, CrateGraph, CrateId, CrateName, Edition, Env, FileId, ProcMacro}; 8use base_db::{CrateDisplayName, CrateGraph, CrateId, CrateName, Edition, Env, FileId, ProcMacro};
9use cargo_workspace::DepKind;
9use cfg::CfgOptions; 10use cfg::CfgOptions;
10use paths::{AbsPath, AbsPathBuf}; 11use paths::{AbsPath, AbsPathBuf};
11use proc_macro_api::ProcMacroClient; 12use proc_macro_api::ProcMacroClient;
@@ -407,23 +408,25 @@ fn cargo_to_crate_graph(
407 } 408 }
408 } 409 }
409 410
410 pkg_crates.entry(pkg).or_insert_with(Vec::new).push(crate_id); 411 pkg_crates.entry(pkg).or_insert_with(Vec::new).push((crate_id, cargo[tgt].kind));
411 } 412 }
412 } 413 }
413 414
414 // Set deps to the core, std and to the lib target of the current package 415 // Set deps to the core, std and to the lib target of the current package
415 for &from in pkg_crates.get(&pkg).into_iter().flatten() { 416 for (from, kind) in pkg_crates.get(&pkg).into_iter().flatten() {
416 if let Some((to, name)) = lib_tgt.clone() { 417 if let Some((to, name)) = lib_tgt.clone() {
417 if to != from { 418 if to != *from && *kind != TargetKind::BuildScript {
419 // (build script can not depend on its library target)
420
418 // For root projects with dashes in their name, 421 // For root projects with dashes in their name,
419 // cargo metadata does not do any normalization, 422 // cargo metadata does not do any normalization,
420 // so we do it ourselves currently 423 // so we do it ourselves currently
421 let name = CrateName::normalize_dashes(&name); 424 let name = CrateName::normalize_dashes(&name);
422 add_dep(&mut crate_graph, from, name, to); 425 add_dep(&mut crate_graph, *from, name, to);
423 } 426 }
424 } 427 }
425 for (name, krate) in public_deps.iter() { 428 for (name, krate) in public_deps.iter() {
426 add_dep(&mut crate_graph, from, name.clone(), *krate); 429 add_dep(&mut crate_graph, *from, name.clone(), *krate);
427 } 430 }
428 } 431 }
429 } 432 }
@@ -434,8 +437,17 @@ fn cargo_to_crate_graph(
434 for dep in cargo[pkg].dependencies.iter() { 437 for dep in cargo[pkg].dependencies.iter() {
435 let name = CrateName::new(&dep.name).unwrap(); 438 let name = CrateName::new(&dep.name).unwrap();
436 if let Some(&to) = pkg_to_lib_crate.get(&dep.pkg) { 439 if let Some(&to) = pkg_to_lib_crate.get(&dep.pkg) {
437 for &from in pkg_crates.get(&pkg).into_iter().flatten() { 440 for (from, kind) in pkg_crates.get(&pkg).into_iter().flatten() {
438 add_dep(&mut crate_graph, from, name.clone(), to) 441 if dep.kind == DepKind::Build && *kind != TargetKind::BuildScript {
442 // Only build scripts may depend on build dependencies.
443 continue;
444 }
445 if dep.kind != DepKind::Build && *kind == TargetKind::BuildScript {
446 // Build scripts may only depend on build dependencies.
447 continue;
448 }
449
450 add_dep(&mut crate_graph, *from, name.clone(), to)
439 } 451 }
440 } 452 }
441 } 453 }
@@ -472,7 +484,7 @@ fn handle_rustc_crates(
472 pkg_to_lib_crate: &mut FxHashMap<la_arena::Idx<crate::PackageData>, CrateId>, 484 pkg_to_lib_crate: &mut FxHashMap<la_arena::Idx<crate::PackageData>, CrateId>,
473 public_deps: &[(CrateName, CrateId)], 485 public_deps: &[(CrateName, CrateId)],
474 cargo: &CargoWorkspace, 486 cargo: &CargoWorkspace,
475 pkg_crates: &FxHashMap<la_arena::Idx<crate::PackageData>, Vec<CrateId>>, 487 pkg_crates: &FxHashMap<la_arena::Idx<crate::PackageData>, Vec<(CrateId, TargetKind)>>,
476) { 488) {
477 let mut rustc_pkg_crates = FxHashMap::default(); 489 let mut rustc_pkg_crates = FxHashMap::default();
478 // The root package of the rustc-dev component is rustc_driver, so we match that 490 // The root package of the rustc-dev component is rustc_driver, so we match that
@@ -541,13 +553,13 @@ fn handle_rustc_crates(
541 if !package.metadata.rustc_private { 553 if !package.metadata.rustc_private {
542 continue; 554 continue;
543 } 555 }
544 for &from in pkg_crates.get(&pkg).into_iter().flatten() { 556 for (from, _) in pkg_crates.get(&pkg).into_iter().flatten() {
545 // Avoid creating duplicate dependencies 557 // Avoid creating duplicate dependencies
546 // This avoids the situation where `from` depends on e.g. `arrayvec`, but 558 // This avoids the situation where `from` depends on e.g. `arrayvec`, but
547 // `rust_analyzer` thinks that it should use the one from the `rustcSource` 559 // `rust_analyzer` thinks that it should use the one from the `rustcSource`
548 // instead of the one from `crates.io` 560 // instead of the one from `crates.io`
549 if !crate_graph[from].dependencies.iter().any(|d| d.name == name) { 561 if !crate_graph[*from].dependencies.iter().any(|d| d.name == name) {
550 add_dep(crate_graph, from, name.clone(), to); 562 add_dep(crate_graph, *from, name.clone(), to);
551 } 563 }
552 } 564 }
553 } 565 }