@@ -428,10 +428,14 @@ pub fn create_bcx<'a, 'cfg>(
428
428
remove_duplicate_doc ( build_config, & units, & mut unit_graph) ;
429
429
}
430
430
431
- if build_config
431
+ let host_kind_requested = build_config
432
432
. requested_kinds
433
433
. 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 ( ) )
435
439
{
436
440
// Rebuild the unit graph, replacing the explicit host targets with
437
441
// CompileKind::Host, merging any dependencies shared with build
@@ -441,7 +445,7 @@ pub fn create_bcx<'a, 'cfg>(
441
445
unit_graph,
442
446
& units,
443
447
& scrape_units,
444
- explicit_host_kind,
448
+ host_kind_requested . then_some ( explicit_host_kind) ,
445
449
) ;
446
450
// This would be nicer with destructuring assignment.
447
451
units = new_graph. 0 ;
@@ -553,29 +557,30 @@ pub fn create_bcx<'a, 'cfg>(
553
557
/// This is used to rebuild the unit graph, sharing host dependencies if possible.
554
558
///
555
559
/// This will translate any unit's `CompileKind::Target(host)` to
556
- /// `CompileKind::Host` if the kind is equal to `to_host`. This also handles
557
- /// generating the unit `dep_hash`, and merging shared units if possible.
560
+ /// `CompileKind::Host` if `to_host` is not `None` and the kind is equal to `to_host`.
561
+ /// This also handles generating the unit `dep_hash`, and merging shared units if possible.
558
562
///
559
563
/// This is necessary because if normal dependencies used `CompileKind::Host`,
560
564
/// there would be no way to distinguish those units from build-dependency
561
- /// units. This can cause a problem if a shared normal/build dependency needs
565
+ /// units or artifact dependency units.
566
+ /// This can cause a problem if a shared normal/build/artifact dependency needs
562
567
/// to link to another dependency whose features differ based on whether or
563
- /// not it is a normal or build dependency. If both units used
568
+ /// not it is a normal, build or artifact dependency. If all units used
564
569
/// `CompileKind::Host`, then they would end up being identical, causing a
565
570
/// collision in the `UnitGraph`, and Cargo would end up randomly choosing one
566
571
/// value or the other.
567
572
///
568
- /// The solution is to keep normal and build dependencies separate when
573
+ /// The solution is to keep normal, build and artifact dependencies separate when
569
574
/// building the unit graph, and then run this second pass which will try to
570
575
/// combine shared dependencies safely. By adding a hash of the dependencies
571
576
/// to the `Unit`, this allows the `CompileKind` to be changed back to `Host`
572
- /// without fear of an unwanted collision.
577
+ /// without fear of an unwanted collision for build-dependencies .
573
578
fn rebuild_unit_graph_shared (
574
579
interner : & UnitInterner ,
575
580
unit_graph : UnitGraph ,
576
581
roots : & [ Unit ] ,
577
582
scrape_units : & [ Unit ] ,
578
- to_host : CompileKind ,
583
+ to_host : Option < CompileKind > ,
579
584
) -> ( Vec < Unit > , Vec < Unit > , UnitGraph ) {
580
585
let mut result = UnitGraph :: new ( ) ;
581
586
// Map of the old unit to the new unit, used to avoid recursing into units
@@ -608,7 +613,7 @@ fn traverse_and_share(
608
613
new_graph : & mut UnitGraph ,
609
614
unit_graph : & UnitGraph ,
610
615
unit : & Unit ,
611
- to_host : CompileKind ,
616
+ to_host : Option < CompileKind > ,
612
617
) -> Unit {
613
618
if let Some ( new_unit) = memo. get ( unit) {
614
619
// Already computed, no need to recompute.
@@ -628,10 +633,9 @@ fn traverse_and_share(
628
633
} )
629
634
. collect ( ) ;
630
635
let new_dep_hash = dep_hash. finish ( ) ;
631
- let new_kind = if unit. kind == to_host {
632
- CompileKind :: Host
633
- } else {
634
- unit. kind
636
+ let new_kind = match to_host {
637
+ Some ( to_host) if to_host == unit. kind => CompileKind :: Host ,
638
+ _ => unit. kind ,
635
639
} ;
636
640
let new_unit = interner. intern (
637
641
& unit. pkg ,
@@ -643,6 +647,7 @@ fn traverse_and_share(
643
647
unit. is_std ,
644
648
new_dep_hash,
645
649
unit. artifact ,
650
+ None ,
646
651
) ;
647
652
assert ! ( memo. insert( unit. clone( ) , new_unit. clone( ) ) . is_none( ) ) ;
648
653
new_graph. entry ( new_unit. clone ( ) ) . or_insert ( new_deps) ;
@@ -801,6 +806,7 @@ fn override_rustc_crate_types(
801
806
unit. is_std ,
802
807
unit. dep_hash ,
803
808
unit. artifact ,
809
+ unit. artifact_target_for_features ,
804
810
)
805
811
} ;
806
812
units[ 0 ] = match unit. target . kind ( ) {
0 commit comments