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