@@ -74,11 +74,12 @@ impl Node {
7474 }
7575}
7676
77- #[ derive( Debug , Copy , Hash , Eq , Clone , PartialEq ) ]
77+ #[ derive( Debug , Hash , Eq , Clone , PartialEq ) ]
7878pub struct Edge {
7979 kind : EdgeKind ,
8080 node : NodeId ,
8181 public : bool ,
82+ artifact : Option < ArtifactEdge > ,
8283}
8384
8485impl Edge {
@@ -93,6 +94,34 @@ impl Edge {
9394 pub fn public ( & self ) -> bool {
9495 self . public
9596 }
97+
98+ pub fn artifact ( & self ) -> Option < & ArtifactEdge > {
99+ self . artifact . as_ref ( )
100+ }
101+ }
102+
103+ #[ derive( Debug , Hash , Eq , Clone , Ord , PartialEq , PartialOrd ) ]
104+ pub struct ArtifactEdge {
105+ kinds : Vec < String > ,
106+ target : Option < String > ,
107+ }
108+
109+ impl ArtifactEdge {
110+ pub fn display ( & self ) -> ArtifactEdgeDisplay < ' _ > {
111+ ArtifactEdgeDisplay ( self )
112+ }
113+ }
114+
115+ pub struct ArtifactEdgeDisplay < ' a > ( & ' a ArtifactEdge ) ;
116+
117+ impl std:: fmt:: Display for ArtifactEdgeDisplay < ' _ > {
118+ fn fmt ( & self , f : & mut std:: fmt:: Formatter < ' _ > ) -> std:: fmt:: Result {
119+ f. write_str ( & self . 0 . kinds . join ( ", " ) ) ?;
120+ if let Some ( target) = & self . 0 . target {
121+ write ! ( f, ", {target}" ) ?;
122+ }
123+ Ok ( ( ) )
124+ }
96125}
97126
98127/// The kind of edge, for separating dependencies into different sections.
@@ -189,7 +218,11 @@ impl<'a> Graph<'a> {
189218 let edges = self . edges ( from) . of_kind ( kind) ;
190219 // Created a sorted list for consistent output.
191220 let mut edges = edges. to_owned ( ) ;
192- edges. sort_unstable_by ( |a, b| self . node ( a. node ( ) ) . cmp ( & self . node ( b. node ( ) ) ) ) ;
221+ edges. sort_unstable_by ( |a, b| {
222+ self . node ( a. node ( ) )
223+ . cmp ( & self . node ( b. node ( ) ) )
224+ . then_with ( || a. artifact . cmp ( & b. artifact ) )
225+ } ) ;
193226 edges
194227 }
195228
@@ -275,6 +308,7 @@ impl<'a> Graph<'a> {
275308 kind : edge. kind ( ) ,
276309 node : new_to_index,
277310 public : edge. public ( ) ,
311+ artifact : edge. artifact ( ) . cloned ( ) ,
278312 } ;
279313 new_graph. edges_mut ( new_from) . add_edge ( new_edge) ;
280314 }
@@ -298,6 +332,7 @@ impl<'a> Graph<'a> {
298332 kind : edge. kind ( ) ,
299333 node : NodeId :: new ( from_idx, self . nodes [ from_idx] . name ( ) ) ,
300334 public : edge. public ( ) ,
335+ artifact : edge. artifact ( ) . cloned ( ) ,
301336 } ;
302337 new_edges[ edge. node ( ) . index ] . add_edge ( new_edge) ;
303338 }
@@ -486,33 +521,48 @@ fn add_pkg(
486521 let dep_pkg = graph. package_map [ & dep_id] ;
487522
488523 for dep in deps {
489- let dep_features_for = match dep
524+ let base_features_for = if features_for != FeaturesFor :: default ( ) {
525+ features_for
526+ } else if dep. is_build ( ) || dep_pkg. proc_macro ( ) {
527+ FeaturesFor :: HostDep
528+ } else {
529+ features_for
530+ } ;
531+
532+ if dep. artifact ( ) . is_some_and ( |artifact| artifact. is_lib ( ) ) {
533+ let dep_index = add_pkg (
534+ graph,
535+ resolve,
536+ resolved_features,
537+ dep_id,
538+ base_features_for,
539+ target_data,
540+ requested_kind,
541+ opts,
542+ ) ;
543+ let new_edge = Edge {
544+ kind : EdgeKind :: Dep ( dep. kind ( ) ) ,
545+ node : dep_index,
546+ public : dep. is_public ( ) ,
547+ artifact : None ,
548+ } ;
549+ add_edge (
550+ graph,
551+ & mut dep_name_map,
552+ from_index,
553+ dep_index,
554+ dep,
555+ new_edge,
556+ opts,
557+ ) ;
558+ }
559+
560+ let dep_features_for = dep
490561 . artifact ( )
491562 . and_then ( |artifact| artifact. target ( ) )
492563 . and_then ( |target| target. to_resolved_compile_target ( requested_kind) )
493- {
494- // Dependency has a `{ …, target = <triple> }`
495- Some ( target) => FeaturesFor :: ArtifactDep ( target) ,
496- // Get the information of the dependent crate from `features_for`.
497- // If a dependent crate is
498- //
499- // * specified as an artifact dep with a `target`, or
500- // * a host dep,
501- //
502- // its transitive deps, including build-deps, need to be built on that target.
503- None if features_for != FeaturesFor :: default ( ) => features_for,
504- // Dependent crate is a normal dep, then back to old rules:
505- //
506- // * normal deps, dev-deps -> inherited target
507- // * build-deps -> host
508- None => {
509- if dep. is_build ( ) || dep_pkg. proc_macro ( ) {
510- FeaturesFor :: HostDep
511- } else {
512- features_for
513- }
514- }
515- } ;
564+ . map ( FeaturesFor :: ArtifactDep )
565+ . unwrap_or ( base_features_for) ;
516566 let dep_index = add_pkg (
517567 graph,
518568 resolve,
@@ -527,26 +577,24 @@ fn add_pkg(
527577 kind : EdgeKind :: Dep ( dep. kind ( ) ) ,
528578 node : dep_index,
529579 public : dep. is_public ( ) ,
580+ artifact : dep. artifact ( ) . map ( |artifact| ArtifactEdge {
581+ kinds : artifact
582+ . kinds ( )
583+ . iter ( )
584+ . map ( |kind| kind. to_string ( ) )
585+ . collect ( ) ,
586+ target : artifact. target ( ) . map ( |target| target. as_str ( ) . to_owned ( ) ) ,
587+ } ) ,
530588 } ;
531- if opts. graph_features {
532- // Add the dependency node with feature nodes in-between.
533- dep_name_map
534- . entry ( dep. name_in_toml ( ) )
535- . or_default ( )
536- . insert ( ( dep_index, dep. is_optional ( ) ) ) ;
537- if dep. uses_default_features ( ) {
538- add_feature ( graph, INTERNED_DEFAULT , Some ( from_index) , new_edge) ;
539- }
540- for feature in dep. features ( ) . iter ( ) {
541- add_feature ( graph, * feature, Some ( from_index) , new_edge) ;
542- }
543- if !dep. uses_default_features ( ) && dep. features ( ) . is_empty ( ) {
544- // No features, use a direct connection.
545- graph. edges_mut ( from_index) . add_edge ( new_edge) ;
546- }
547- } else {
548- graph. edges_mut ( from_index) . add_edge ( new_edge) ;
549- }
589+ add_edge (
590+ graph,
591+ & mut dep_name_map,
592+ from_index,
593+ dep_index,
594+ dep,
595+ new_edge,
596+ opts,
597+ ) ;
550598 }
551599 }
552600 if opts. graph_features {
@@ -561,6 +609,36 @@ fn add_pkg(
561609 from_index
562610}
563611
612+ fn add_edge (
613+ graph : & mut Graph < ' _ > ,
614+ dep_name_map : & mut HashMap < InternedString , HashSet < ( NodeId , bool ) > > ,
615+ from_index : NodeId ,
616+ dep_index : NodeId ,
617+ dep : & crate :: core:: Dependency ,
618+ new_edge : Edge ,
619+ opts : & TreeOptions ,
620+ ) {
621+ if opts. graph_features {
622+ // Add the dependency node with feature nodes in-between.
623+ dep_name_map
624+ . entry ( dep. name_in_toml ( ) )
625+ . or_default ( )
626+ . insert ( ( dep_index, dep. is_optional ( ) ) ) ;
627+ if dep. uses_default_features ( ) {
628+ add_feature ( graph, INTERNED_DEFAULT , Some ( from_index) , new_edge. clone ( ) ) ;
629+ }
630+ for feature in dep. features ( ) . iter ( ) {
631+ add_feature ( graph, * feature, Some ( from_index) , new_edge. clone ( ) ) ;
632+ }
633+ if !dep. uses_default_features ( ) && dep. features ( ) . is_empty ( ) {
634+ // No features, use a direct connection.
635+ graph. edges_mut ( from_index) . add_edge ( new_edge) ;
636+ }
637+ } else {
638+ graph. edges_mut ( from_index) . add_edge ( new_edge) ;
639+ }
640+ }
641+
564642/// Adds a feature node between two nodes.
565643///
566644/// That is, it adds the following:
@@ -593,13 +671,15 @@ fn add_feature(
593671 kind : to. kind ( ) ,
594672 node : node_index,
595673 public : to. public ( ) ,
674+ artifact : to. artifact ( ) . cloned ( ) ,
596675 } ;
597676 graph. edges_mut ( from) . add_edge ( from_edge) ;
598677 }
599678 let to_edge = Edge {
600679 kind : EdgeKind :: Feature ,
601680 node : to. node ( ) ,
602681 public : true ,
682+ artifact : to. artifact ( ) . cloned ( ) ,
603683 } ;
604684 graph. edges_mut ( node_index) . add_edge ( to_edge) ;
605685 ( missing, node_index)
@@ -638,6 +718,7 @@ fn add_cli_features(
638718 kind : EdgeKind :: Feature ,
639719 node : package_index,
640720 public : true ,
721+ artifact : None ,
641722 } ;
642723 let index = add_feature ( graph, feature, None , feature_edge) . 1 ;
643724 graph. cli_features . insert ( index) ;
@@ -673,6 +754,7 @@ fn add_cli_features(
673754 kind : EdgeKind :: Feature ,
674755 node : package_index,
675756 public : true ,
757+ artifact : None ,
676758 } ;
677759 let index = add_feature ( graph, dep_name, None , feature_edge) . 1 ;
678760 graph. cli_features . insert ( index) ;
@@ -681,6 +763,7 @@ fn add_cli_features(
681763 kind : EdgeKind :: Feature ,
682764 node : dep_index,
683765 public : true ,
766+ artifact : None ,
684767 } ;
685768 let index = add_feature ( graph, dep_feature, None , dep_edge) . 1 ;
686769 graph. cli_features . insert ( index) ;
@@ -742,6 +825,7 @@ fn add_feature_rec(
742825 kind : EdgeKind :: Feature ,
743826 node : package_index,
744827 public : true ,
828+ artifact : None ,
745829 } ;
746830 let ( missing, feat_index) = add_feature ( graph, * dep_name, Some ( from) , feature_edge) ;
747831 // Don't recursive if the edge already exists to deal with cycles.
@@ -793,13 +877,15 @@ fn add_feature_rec(
793877 kind : EdgeKind :: Feature ,
794878 node : package_index,
795879 public : true ,
880+ artifact : None ,
796881 } ;
797882 add_feature ( graph, * dep_name, Some ( from) , feature_edge) ;
798883 }
799884 let dep_edge = Edge {
800885 kind : EdgeKind :: Feature ,
801886 node : dep_index,
802887 public : true ,
888+ artifact : None ,
803889 } ;
804890 let ( missing, feat_index) =
805891 add_feature ( graph, * dep_feature, Some ( from) , dep_edge) ;
0 commit comments