Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
89 changes: 70 additions & 19 deletions src/cargo/core/compiler/unit_dependencies.rs
Original file line number Diff line number Diff line change
Expand Up @@ -310,6 +310,16 @@ fn compute_deps(
let dep_unit_for = unit_for.with_dependency(unit, dep_lib, unit_for.root_compile_kind());

let manifest_deps = deps.iter().map(|d| (*d).clone()).collect::<Vec<_>>();
let lib_dep_name = if deps.iter().any(|dep| dep.artifact().is_some()) {
state.resolve().lib_dependency_name(
unit.pkg.package_id(),
dep_pkg_id,
deps.iter().copied(),
dep_lib,
)?
} else {
None
};

let start = ret.len();
if state.gctx.cli_unstable().dual_proc_macros
Expand All @@ -322,6 +332,7 @@ fn compute_deps(
dep_pkg,
dep_lib,
Some(manifest_deps.clone()),
lib_dep_name,
dep_unit_for,
unit.kind,
mode,
Expand All @@ -334,6 +345,7 @@ fn compute_deps(
dep_pkg,
dep_lib,
Some(manifest_deps),
lib_dep_name,
dep_unit_for,
CompileKind::Host,
mode,
Expand All @@ -347,6 +359,7 @@ fn compute_deps(
dep_pkg,
dep_lib,
Some(manifest_deps),
lib_dep_name,
dep_unit_for,
unit.kind.for_target(dep_lib),
mode,
Expand Down Expand Up @@ -426,6 +439,7 @@ fn compute_deps(
&unit.pkg,
t,
None, // artificial
None,
UnitFor::new_normal(unit_for.root_compile_kind()),
unit.kind.for_target(t),
CompileMode::Build,
Expand All @@ -452,6 +466,7 @@ fn calc_artifact_deps<'a>(
let mut has_artifact_lib = false;
let mut maybe_non_artifact_lib = false;
let artifact_pkg = state.get(dep_id);
let all_artifact = deps.iter().all(|d| d.artifact().is_some());
for dep in deps {
let Some(artifact) = dep.artifact() else {
maybe_non_artifact_lib = true;
Expand All @@ -478,6 +493,7 @@ fn calc_artifact_deps<'a>(
.unwrap_or(unit.kind),
artifact_pkg,
dep,
all_artifact.then_some(*dep),
)?);
}
}
Expand Down Expand Up @@ -522,6 +538,7 @@ fn compute_deps_custom_build(
&unit.pkg,
&unit.target,
None, // artificial
None,
script_unit_for,
// Build scripts always compiled for the host.
CompileKind::Host,
Expand All @@ -546,6 +563,7 @@ fn compute_deps_custom_build(
let root_unit_compile_target = unit_for.root_compile_kind();
let unit_for = UnitFor::new_host(/*host_features*/ true, root_unit_compile_target);
for (dep_pkg_id, deps) in state.deps(unit, script_unit_for) {
let all_artifact = deps.iter().all(|d| d.artifact().is_some());
for dep in deps {
if dep.kind() != DepKind::Build || dep.artifact().is_none() {
continue;
Expand All @@ -565,6 +583,7 @@ fn compute_deps_custom_build(
resolved_artifact_compile_kind.unwrap_or(CompileKind::Host),
artifact_pkg,
dep,
all_artifact.then_some(dep),
)?);
}
}
Expand All @@ -589,6 +608,7 @@ fn artifact_targets_to_unit_deps(
compile_kind: CompileKind,
artifact_pkg: &Package,
dep: &Dependency,
naming_dep: Option<&Dependency>,
) -> CargoResult<Vec<UnitDep>> {
let ret =
match_artifacts_kind_with_targets(dep, artifact_pkg.targets(), parent.pkg.name().as_str())?
Expand All @@ -608,32 +628,41 @@ fn artifact_targets_to_unit_deps(
_ => false,
})
.map(|target_kind| {
let mut target = target.clone();
target.set_kind(TargetKind::Lib(vec![target_kind.clone()]));
let name_override = naming_dep.map(|dep| {
Resolve::dep_extern_crate_name_and_dep_name(dep, &target)
});
new_unit_dep(
state,
parent,
artifact_pkg,
target
.clone()
.set_kind(TargetKind::Lib(vec![target_kind.clone()])),
&target,
None, // TBD
name_override,
parent_unit_for,
compile_kind,
CompileMode::Build,
dep.artifact(),
)
}),
) as Box<dyn Iterator<Item = _>>,
_ => Box::new(std::iter::once(new_unit_dep(
state,
parent,
artifact_pkg,
target,
None, // TBD
parent_unit_for,
compile_kind,
CompileMode::Build,
dep.artifact(),
))),
_ => {
let name_override = naming_dep
.map(|dep| Resolve::dep_extern_crate_name_and_dep_name(dep, target));
Box::new(std::iter::once(new_unit_dep(
state,
parent,
artifact_pkg,
target,
None, // TBD
name_override,
parent_unit_for,
compile_kind,
CompileMode::Build,
dep.artifact(),
)))
}
}
})
.collect::<Result<Vec<_>, _>>()?;
Expand All @@ -659,12 +688,23 @@ fn compute_deps_doc(
// However, for plugins/proc macros, deps should be built like normal.
let mode = check_or_build_mode(unit.mode, dep_lib);
let dep_unit_for = unit_for.with_dependency(unit, dep_lib, unit_for.root_compile_kind());
let lib_dep_name = if deps.iter().any(|dep| dep.artifact().is_some()) {
state.resolve().lib_dependency_name(
unit.pkg.package_id(),
id,
deps.iter().copied(),
dep_lib,
)?
} else {
None
};
let lib_unit_dep = new_unit_dep(
state,
unit,
dep_pkg,
dep_lib,
None, // not checking unused deps
lib_dep_name,
dep_unit_for,
unit.kind.for_target(dep_lib),
mode,
Expand All @@ -679,6 +719,7 @@ fn compute_deps_doc(
dep_pkg,
dep_lib,
None, // not checking unused deps
lib_dep_name,
dep_unit_for,
unit.kind.for_target(dep_lib),
unit.mode,
Expand Down Expand Up @@ -713,6 +754,7 @@ fn compute_deps_doc(
&unit.pkg,
lib,
None, // not checking unused deps
None,
dep_unit_for,
unit.kind.for_target(lib),
unit.mode,
Expand All @@ -733,6 +775,7 @@ fn compute_deps_doc(
&scrape_unit.pkg,
&scrape_unit.target,
None, // not checking unused deps
None,
scrape_unit_for,
scrape_unit.kind,
scrape_unit.mode,
Expand Down Expand Up @@ -762,6 +805,7 @@ fn maybe_lib(
&unit.pkg,
t,
None,
None,
dep_unit_for,
unit.kind.for_target(t),
mode,
Expand Down Expand Up @@ -824,6 +868,7 @@ fn dep_build_script(
&unit.pkg,
t,
None, // artificial
None,
script_unit_for,
unit.kind,
CompileMode::RunCustomBuild,
Expand Down Expand Up @@ -861,6 +906,7 @@ fn new_unit_dep(
pkg: &Package,
target: &Target,
manifest_deps: Option<Vec<Dependency>>,
name_override: Option<(InternedString, Option<InternedString>)>,
unit_for: UnitFor,
kind: CompileKind,
mode: CompileMode,
Expand All @@ -880,6 +926,7 @@ fn new_unit_dep(
pkg,
target,
manifest_deps,
name_override,
unit_for,
kind,
mode,
Expand All @@ -894,17 +941,21 @@ fn new_unit_dep_with_profile(
pkg: &Package,
target: &Target,
manifest_deps: Option<Vec<Dependency>>,
name_override: Option<(InternedString, Option<InternedString>)>,
unit_for: UnitFor,
kind: CompileKind,
mode: CompileMode,
profile: Profile,
artifact: Option<&Artifact>,
) -> CargoResult<UnitDep> {
let (extern_crate_name, dep_name) = state.resolve().extern_crate_name_and_dep_name(
parent.pkg.package_id(),
pkg.package_id(),
target,
)?;
let (extern_crate_name, dep_name) = match name_override {
Some(name) => name,
None => state.resolve().extern_crate_name_and_dep_name(
parent.pkg.package_id(),
pkg.package_id(),
target,
)?,
};
let public = state
.resolve()
.is_public_dep(parent.pkg.package_id(), pkg.package_id());
Expand Down
72 changes: 65 additions & 7 deletions src/cargo/core/resolver/resolve.rs
Original file line number Diff line number Diff line change
Expand Up @@ -419,12 +419,19 @@ unable to verify that `{0}` is the same as when the lockfile was generated
self.dependencies_listed(from, to)
};

let target_crate_name = || (to_target.crate_name(), None);
let mut name_pairs = deps.iter().map(|d| {
d.explicit_name_in_toml()
.map(|s| (s.as_str().replace("-", "_"), Some(s)))
.unwrap_or_else(target_crate_name)
});
Self::extern_crate_name_and_dep_name_from_deps(from, to, deps.iter(), to_target)
}

fn extern_crate_name_and_dep_name_from_deps<'a>(
from: PackageId,
to: PackageId,
deps: impl IntoIterator<Item = &'a Dependency>,
to_target: &Target,
) -> CargoResult<(InternedString, Option<InternedString>)> {
let target_crate_name = || (to_target.crate_name().into(), None);
let mut name_pairs = deps
.into_iter()
.map(|d| Self::dep_extern_crate_name_and_dep_name(d, to_target));
let (extern_crate_name, dep_name) = name_pairs.next().unwrap_or_else(target_crate_name);
for (n, _) in name_pairs {
anyhow::ensure!(
Expand All @@ -434,7 +441,58 @@ unable to verify that `{0}` is the same as when the lockfile was generated
to,
);
}
Ok((extern_crate_name.into(), dep_name))
Ok((extern_crate_name, dep_name))
}

pub fn dep_extern_crate_name_and_dep_name(
dep: &Dependency,
to_target: &Target,
) -> (InternedString, Option<InternedString>) {
dep.explicit_name_in_toml()
.map(|name| (name.as_str().replace('-', "_").into(), Some(name)))
.unwrap_or_else(|| (to_target.crate_name().into(), None))
}

pub fn lib_dependency_name<'a>(
&self,
from: PackageId,
to: PackageId,
deps: impl IntoIterator<Item = &'a Dependency>,
to_target: &Target,
) -> CargoResult<Option<(InternedString, Option<InternedString>)>> {
let deps = deps.into_iter().collect::<Vec<_>>();
if !deps.iter().all(|dep| dep.artifact().is_some()) {
return Self::extern_crate_name_and_dep_name_from_deps(
from,
to,
deps.into_iter(),
to_target,
)
.map(Some);
}

let mut names = deps
.into_iter()
.filter(|dep| dep.artifact().is_some_and(|artifact| artifact.is_lib()))
.map(|dep| Self::dep_extern_crate_name_and_dep_name(dep, to_target))
.collect::<Vec<_>>();

if names.is_empty() {
return Ok(None);
}

names.sort();
names.dedup();
let (extern_crate_name, dep_name) = names[0];
for (name, _) in &names[1..] {
anyhow::ensure!(
*name == extern_crate_name,
"the crate `{}` depends on crate `{}` multiple times with different names",
from,
to,
);
}
Ok(Some((extern_crate_name, dep_name)))
}

fn dependencies_listed(&self, from: PackageId, to: PackageId) -> &HashSet<Dependency> {
Expand Down
Loading