Fix build script dependencies
This commit is contained in:
parent
9a431c26f4
commit
a272cdfecd
@ -119,6 +119,32 @@ pub struct RustAnalyzerPackageMetaData {
|
||||
pub struct PackageDependency {
|
||||
pub pkg: Package,
|
||||
pub name: String,
|
||||
pub kind: DepKind,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Eq, PartialEq)]
|
||||
pub enum DepKind {
|
||||
/// Available to the library, binary, and dev targets in the package (but not the build script).
|
||||
Normal,
|
||||
/// Available only to test and bench targets (and the library target, when built with `cfg(test)`).
|
||||
Dev,
|
||||
/// Available only to the build script target.
|
||||
Build,
|
||||
}
|
||||
|
||||
impl DepKind {
|
||||
fn new(list: &[cargo_metadata::DepKindInfo]) -> Self {
|
||||
for info in list {
|
||||
match info.kind {
|
||||
cargo_metadata::DependencyKind::Normal => return Self::Normal,
|
||||
cargo_metadata::DependencyKind::Development => return Self::Dev,
|
||||
cargo_metadata::DependencyKind::Build => return Self::Build,
|
||||
cargo_metadata::DependencyKind::Unknown => continue,
|
||||
}
|
||||
}
|
||||
|
||||
Self::Normal
|
||||
}
|
||||
}
|
||||
|
||||
/// Information associated with a package's target
|
||||
@ -144,6 +170,7 @@ pub enum TargetKind {
|
||||
Example,
|
||||
Test,
|
||||
Bench,
|
||||
BuildScript,
|
||||
Other,
|
||||
}
|
||||
|
||||
@ -155,6 +182,7 @@ impl TargetKind {
|
||||
"test" => TargetKind::Test,
|
||||
"bench" => TargetKind::Bench,
|
||||
"example" => TargetKind::Example,
|
||||
"custom-build" => TargetKind::BuildScript,
|
||||
"proc-macro" => TargetKind::Lib,
|
||||
_ if kind.contains("lib") => TargetKind::Lib,
|
||||
_ => continue,
|
||||
@ -301,7 +329,11 @@ impl CargoWorkspace {
|
||||
continue;
|
||||
}
|
||||
};
|
||||
let dep = PackageDependency { name: dep_node.name, pkg };
|
||||
let dep = PackageDependency {
|
||||
name: dep_node.name,
|
||||
pkg,
|
||||
kind: DepKind::new(&dep_node.dep_kinds),
|
||||
};
|
||||
packages[source].dependencies.push(dep);
|
||||
}
|
||||
packages[source].active_features.extend(node.features);
|
||||
|
@ -6,6 +6,7 @@ use std::{collections::VecDeque, fmt, fs, path::Path, process::Command};
|
||||
|
||||
use anyhow::{Context, Result};
|
||||
use base_db::{CrateDisplayName, CrateGraph, CrateId, CrateName, Edition, Env, FileId, ProcMacro};
|
||||
use cargo_workspace::DepKind;
|
||||
use cfg::CfgOptions;
|
||||
use paths::{AbsPath, AbsPathBuf};
|
||||
use proc_macro_api::ProcMacroClient;
|
||||
@ -407,23 +408,25 @@ fn cargo_to_crate_graph(
|
||||
}
|
||||
}
|
||||
|
||||
pkg_crates.entry(pkg).or_insert_with(Vec::new).push(crate_id);
|
||||
pkg_crates.entry(pkg).or_insert_with(Vec::new).push((crate_id, cargo[tgt].kind));
|
||||
}
|
||||
}
|
||||
|
||||
// Set deps to the core, std and to the lib target of the current package
|
||||
for &from in pkg_crates.get(&pkg).into_iter().flatten() {
|
||||
for (from, kind) in pkg_crates.get(&pkg).into_iter().flatten() {
|
||||
if let Some((to, name)) = lib_tgt.clone() {
|
||||
if to != from {
|
||||
if to != *from && *kind != TargetKind::BuildScript {
|
||||
// (build script can not depend on its library target)
|
||||
|
||||
// For root projects with dashes in their name,
|
||||
// cargo metadata does not do any normalization,
|
||||
// so we do it ourselves currently
|
||||
let name = CrateName::normalize_dashes(&name);
|
||||
add_dep(&mut crate_graph, from, name, to);
|
||||
add_dep(&mut crate_graph, *from, name, to);
|
||||
}
|
||||
}
|
||||
for (name, krate) in public_deps.iter() {
|
||||
add_dep(&mut crate_graph, from, name.clone(), *krate);
|
||||
add_dep(&mut crate_graph, *from, name.clone(), *krate);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -434,8 +437,17 @@ fn cargo_to_crate_graph(
|
||||
for dep in cargo[pkg].dependencies.iter() {
|
||||
let name = CrateName::new(&dep.name).unwrap();
|
||||
if let Some(&to) = pkg_to_lib_crate.get(&dep.pkg) {
|
||||
for &from in pkg_crates.get(&pkg).into_iter().flatten() {
|
||||
add_dep(&mut crate_graph, from, name.clone(), to)
|
||||
for (from, kind) in pkg_crates.get(&pkg).into_iter().flatten() {
|
||||
if dep.kind == DepKind::Build && *kind != TargetKind::BuildScript {
|
||||
// Only build scripts may depend on build dependencies.
|
||||
continue;
|
||||
}
|
||||
if dep.kind != DepKind::Build && *kind == TargetKind::BuildScript {
|
||||
// Build scripts may only depend on build dependencies.
|
||||
continue;
|
||||
}
|
||||
|
||||
add_dep(&mut crate_graph, *from, name.clone(), to)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -472,7 +484,7 @@ fn handle_rustc_crates(
|
||||
pkg_to_lib_crate: &mut FxHashMap<la_arena::Idx<crate::PackageData>, CrateId>,
|
||||
public_deps: &[(CrateName, CrateId)],
|
||||
cargo: &CargoWorkspace,
|
||||
pkg_crates: &FxHashMap<la_arena::Idx<crate::PackageData>, Vec<CrateId>>,
|
||||
pkg_crates: &FxHashMap<la_arena::Idx<crate::PackageData>, Vec<(CrateId, TargetKind)>>,
|
||||
) {
|
||||
let mut rustc_pkg_crates = FxHashMap::default();
|
||||
// The root package of the rustc-dev component is rustc_driver, so we match that
|
||||
@ -541,13 +553,13 @@ fn handle_rustc_crates(
|
||||
if !package.metadata.rustc_private {
|
||||
continue;
|
||||
}
|
||||
for &from in pkg_crates.get(&pkg).into_iter().flatten() {
|
||||
for (from, _) in pkg_crates.get(&pkg).into_iter().flatten() {
|
||||
// Avoid creating duplicate dependencies
|
||||
// This avoids the situation where `from` depends on e.g. `arrayvec`, but
|
||||
// `rust_analyzer` thinks that it should use the one from the `rustcSource`
|
||||
// instead of the one from `crates.io`
|
||||
if !crate_graph[from].dependencies.iter().any(|d| d.name == name) {
|
||||
add_dep(crate_graph, from, name.clone(), to);
|
||||
if !crate_graph[*from].dependencies.iter().any(|d| d.name == name) {
|
||||
add_dep(crate_graph, *from, name.clone(), to);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -159,7 +159,7 @@ impl CargoTargetSpec {
|
||||
TargetKind::Lib => {
|
||||
buf.push("--lib".to_string());
|
||||
}
|
||||
TargetKind::Other => (),
|
||||
TargetKind::Other | TargetKind::BuildScript => (),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user