Skip to content

Commit 1a01ae0

Browse files
committed
fix: deduplicate dependencies by artifact target
Signed-off-by: Roman Volosatovs <[email protected]>
1 parent 70898e5 commit 1a01ae0

File tree

5 files changed

+36
-11
lines changed

5 files changed

+36
-11
lines changed

src/cargo/core/compiler/standard_lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -214,6 +214,7 @@ pub fn generate_std_roots(
214214
/*is_std*/ true,
215215
/*dep_hash*/ 0,
216216
IsArtifact::No,
217+
None,
217218
));
218219
}
219220
}

src/cargo/core/compiler/unit.rs

+14-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
1-
use crate::core::compiler::{unit_dependencies::IsArtifact, CompileKind, CompileMode, CrateType};
1+
use crate::core::compiler::unit_dependencies::IsArtifact;
2+
use crate::core::compiler::{CompileKind, CompileMode, CompileTarget, CrateType};
23
use crate::core::manifest::{Target, TargetKind};
3-
use crate::core::{profiles::Profile, Package};
4+
use crate::core::profiles::Profile;
5+
use crate::core::Package;
46
use crate::util::hex::short_hash;
57
use crate::util::interning::InternedString;
68
use crate::util::Config;
@@ -72,6 +74,14 @@ pub struct UnitInner {
7274
/// This value initially starts as 0, and then is filled in via a
7375
/// second-pass after all the unit dependencies have been computed.
7476
pub dep_hash: u64,
77+
78+
/// This is only set for artifact dependencies which have their
79+
/// `<target-triple>|target` set.
80+
/// If so, this information is used as part of the key for resolving their features,
81+
/// allowing for target-dependent feature resolution within the entire dependency tree.
82+
/// Note that this target corresponds to the target used to build the units in that
83+
/// dependency tree, too, but this copy of it is specifically used for feature lookup.
84+
pub artifact_target_for_features: Option<CompileTarget>,
7585
}
7686

7787
impl UnitInner {
@@ -184,6 +194,7 @@ impl UnitInterner {
184194
is_std: bool,
185195
dep_hash: u64,
186196
artifact: IsArtifact,
197+
artifact_target_for_features: Option<CompileTarget>,
187198
) -> Unit {
188199
let target = match (is_std, target.kind()) {
189200
// This is a horrible hack to support build-std. `libstd` declares
@@ -216,6 +227,7 @@ impl UnitInterner {
216227
is_std,
217228
dep_hash,
218229
artifact,
230+
artifact_target_for_features,
219231
});
220232
Unit { inner }
221233
}

src/cargo/core/compiler/unit_dependencies.rs

+6
Original file line numberDiff line numberDiff line change
@@ -885,6 +885,11 @@ fn new_unit_dep_with_profile(
885885
.resolve()
886886
.is_public_dep(parent.pkg.package_id(), pkg.package_id());
887887
let features_for = unit_for.map_to_features_for(artifact);
888+
let artifact_target_for_features = if let FeaturesFor::ArtifactDep(target) = features_for {
889+
Some(target)
890+
} else {
891+
None
892+
};
888893
let features = state.activated_features(pkg.package_id(), features_for);
889894
let unit = state.interner.intern(
890895
pkg,
@@ -896,6 +901,7 @@ fn new_unit_dep_with_profile(
896901
state.is_std,
897902
/*dep_hash*/ 0,
898903
artifact.map_or(IsArtifact::No, |_| IsArtifact::Yes),
904+
artifact_target_for_features,
899905
);
900906
Ok(UnitDep {
901907
unit,

src/cargo/ops/cargo_compile/mod.rs

+14-9
Original file line numberDiff line numberDiff line change
@@ -428,10 +428,14 @@ pub fn create_bcx<'a, 'cfg>(
428428
remove_duplicate_doc(build_config, &units, &mut unit_graph);
429429
}
430430

431-
if build_config
431+
let host_kind_requested = build_config
432432
.requested_kinds
433433
.iter()
434-
.any(CompileKind::is_host)
434+
.any(CompileKind::is_host);
435+
if host_kind_requested
436+
|| unit_graph
437+
.iter()
438+
.any(|unit| unit.0.artifact_target_for_features.is_some())
435439
{
436440
// Rebuild the unit graph, replacing the explicit host targets with
437441
// CompileKind::Host, merging any dependencies shared with build
@@ -441,7 +445,7 @@ pub fn create_bcx<'a, 'cfg>(
441445
unit_graph,
442446
&units,
443447
&scrape_units,
444-
explicit_host_kind,
448+
host_kind_requested.then_some(explicit_host_kind),
445449
);
446450
// This would be nicer with destructuring assignment.
447451
units = new_graph.0;
@@ -575,7 +579,7 @@ fn rebuild_unit_graph_shared(
575579
unit_graph: UnitGraph,
576580
roots: &[Unit],
577581
scrape_units: &[Unit],
578-
to_host: CompileKind,
582+
to_host: Option<CompileKind>,
579583
) -> (Vec<Unit>, Vec<Unit>, UnitGraph) {
580584
let mut result = UnitGraph::new();
581585
// Map of the old unit to the new unit, used to avoid recursing into units
@@ -608,7 +612,7 @@ fn traverse_and_share(
608612
new_graph: &mut UnitGraph,
609613
unit_graph: &UnitGraph,
610614
unit: &Unit,
611-
to_host: CompileKind,
615+
to_host: Option<CompileKind>,
612616
) -> Unit {
613617
if let Some(new_unit) = memo.get(unit) {
614618
// Already computed, no need to recompute.
@@ -628,10 +632,9 @@ fn traverse_and_share(
628632
})
629633
.collect();
630634
let new_dep_hash = dep_hash.finish();
631-
let new_kind = if unit.kind == to_host {
632-
CompileKind::Host
633-
} else {
634-
unit.kind
635+
let new_kind = match to_host {
636+
Some(to_host) if to_host == unit.kind => CompileKind::Host,
637+
_ => unit.kind,
635638
};
636639
let new_unit = interner.intern(
637640
&unit.pkg,
@@ -643,6 +646,7 @@ fn traverse_and_share(
643646
unit.is_std,
644647
new_dep_hash,
645648
unit.artifact,
649+
None,
646650
);
647651
assert!(memo.insert(unit.clone(), new_unit.clone()).is_none());
648652
new_graph.entry(new_unit.clone()).or_insert(new_deps);
@@ -801,6 +805,7 @@ fn override_rustc_crate_types(
801805
unit.is_std,
802806
unit.dep_hash,
803807
unit.artifact,
808+
unit.artifact_target_for_features,
804809
)
805810
};
806811
units[0] = match unit.target.kind() {

src/cargo/ops/cargo_compile/unit_generator.rs

+1
Original file line numberDiff line numberDiff line change
@@ -171,6 +171,7 @@ impl<'a> UnitGenerator<'a, '_> {
171171
/*is_std*/ false,
172172
/*dep_hash*/ 0,
173173
IsArtifact::No,
174+
None,
174175
)
175176
})
176177
.collect()

0 commit comments

Comments
 (0)