@@ -47,6 +47,11 @@ struct State<'a, 'cfg> {
47
47
target_data : & ' a RustcTargetData ,
48
48
profiles : & ' a Profiles ,
49
49
interner : & ' a UnitInterner ,
50
+
51
+ /// A set of edges in `unit_dependencies` where (a, b) means that the
52
+ /// dependency from a to b was added purely because it was a dev-dependency.
53
+ /// This is used during `connect_run_custom_build_deps`.
54
+ dev_dependency_edges : HashSet < ( Unit , Unit ) > ,
50
55
}
51
56
52
57
pub fn build_unit_dependencies < ' a , ' cfg > (
@@ -86,6 +91,7 @@ pub fn build_unit_dependencies<'a, 'cfg>(
86
91
target_data,
87
92
profiles,
88
93
interner,
94
+ dev_dependency_edges : HashSet :: new ( ) ,
89
95
} ;
90
96
91
97
let std_unit_deps = calc_deps_of_std ( & mut state, std_roots) ?;
@@ -98,7 +104,7 @@ pub fn build_unit_dependencies<'a, 'cfg>(
98
104
attach_std_deps ( & mut state, std_roots, std_unit_deps) ;
99
105
}
100
106
101
- connect_run_custom_build_deps ( & mut state. unit_dependencies ) ;
107
+ connect_run_custom_build_deps ( & mut state) ;
102
108
103
109
// Dependencies are used in tons of places throughout the backend, many of
104
110
// which affect the determinism of the build itself. As a result be sure
@@ -258,7 +264,8 @@ fn compute_deps(
258
264
} ) ;
259
265
260
266
let mut ret = Vec :: new ( ) ;
261
- for ( id, _) in filtered_deps {
267
+ let mut dev_deps = Vec :: new ( ) ;
268
+ for ( id, deps) in filtered_deps {
262
269
let pkg = state. get ( id) ;
263
270
let lib = match pkg. targets ( ) . iter ( ) . find ( |t| t. is_lib ( ) ) {
264
271
Some ( t) => t,
@@ -267,6 +274,7 @@ fn compute_deps(
267
274
let mode = check_or_build_mode ( unit. mode , lib) ;
268
275
let dep_unit_for = unit_for. with_dependency ( unit, lib) ;
269
276
277
+ let start = ret. len ( ) ;
270
278
if state. config . cli_unstable ( ) . dual_proc_macros && lib. proc_macro ( ) && !unit. kind . is_host ( )
271
279
{
272
280
let unit_dep = new_unit_dep ( state, unit, pkg, lib, dep_unit_for, unit. kind , mode) ?;
@@ -286,7 +294,18 @@ fn compute_deps(
286
294
) ?;
287
295
ret. push ( unit_dep) ;
288
296
}
297
+
298
+ // If the unit added was a dev-dependency unit, then record that in the
299
+ // dev-dependencies array. We'll add this to
300
+ // `state.dev_dependency_edges` at the end and process it later in
301
+ // `connect_run_custom_build_deps`.
302
+ if deps. iter ( ) . all ( |d| !d. is_transitive ( ) ) {
303
+ for dep in ret[ start..] . iter ( ) {
304
+ dev_deps. push ( ( unit. clone ( ) , dep. unit . clone ( ) ) ) ;
305
+ }
306
+ }
289
307
}
308
+ state. dev_dependency_edges . extend ( dev_deps) ;
290
309
291
310
// If this target is a build script, then what we've collected so far is
292
311
// all we need. If this isn't a build script, then it depends on the
@@ -617,26 +636,18 @@ fn new_unit_dep_with_profile(
617
636
///
618
637
/// Here we take the entire `deps` map and add more dependencies from execution
619
638
/// of one build script to execution of another build script.
620
- fn connect_run_custom_build_deps ( unit_dependencies : & mut UnitGraph ) {
639
+ fn connect_run_custom_build_deps ( state : & mut State < ' _ , ' _ > ) {
621
640
let mut new_deps = Vec :: new ( ) ;
622
641
623
642
{
643
+ let state = & * state;
624
644
// First up build a reverse dependency map. This is a mapping of all
625
645
// `RunCustomBuild` known steps to the unit which depends on them. For
626
646
// example a library might depend on a build script, so this map will
627
647
// have the build script as the key and the library would be in the
628
648
// value's set.
629
- //
630
- // Note that as an important part here we're skipping "test" units. Test
631
- // units depend on the execution of a build script, but
632
- // links-dependencies only propagate through `[dependencies]`, nothing
633
- // else. We don't want to pull in a links-dependency through a
634
- // dev-dependency since that could create a cycle.
635
649
let mut reverse_deps_map = HashMap :: new ( ) ;
636
- for ( unit, deps) in unit_dependencies. iter ( ) {
637
- if unit. mode . is_any_test ( ) {
638
- continue ;
639
- }
650
+ for ( unit, deps) in state. unit_dependencies . iter ( ) {
640
651
for dep in deps {
641
652
if dep. unit . mode == CompileMode :: RunCustomBuild {
642
653
reverse_deps_map
@@ -656,7 +667,8 @@ fn connect_run_custom_build_deps(unit_dependencies: &mut UnitGraph) {
656
667
// `links`, then we depend on that package's build script! Here we use
657
668
// `dep_build_script` to manufacture an appropriate build script unit to
658
669
// depend on.
659
- for unit in unit_dependencies
670
+ for unit in state
671
+ . unit_dependencies
660
672
. keys ( )
661
673
. filter ( |k| k. mode == CompileMode :: RunCustomBuild )
662
674
{
@@ -670,16 +682,34 @@ fn connect_run_custom_build_deps(unit_dependencies: &mut UnitGraph) {
670
682
let to_add = reverse_deps
671
683
. iter ( )
672
684
// Get all sibling dependencies of `unit`
673
- . flat_map ( |reverse_dep| unit_dependencies[ reverse_dep] . iter ( ) )
685
+ . flat_map ( |reverse_dep| {
686
+ state. unit_dependencies [ reverse_dep]
687
+ . iter ( )
688
+ . map ( move |a| ( reverse_dep, a) )
689
+ } )
674
690
// Only deps with `links`.
675
- . filter ( |other| {
691
+ . filter ( |( _parent , other) | {
676
692
other. unit . pkg != unit. pkg
677
693
&& other. unit . target . is_linkable ( )
678
694
&& other. unit . pkg . manifest ( ) . links ( ) . is_some ( )
679
695
} )
696
+ // Skip dependencies induced via dev-dependencies since
697
+ // connections between `links` and build scripts only happens
698
+ // via normal dependencies. Otherwise since dev-dependencies can
699
+ // be cyclic we could have cyclic build-script executions.
700
+ . filter_map ( move |( parent, other) | {
701
+ if state
702
+ . dev_dependency_edges
703
+ . contains ( & ( ( * parent) . clone ( ) , other. unit . clone ( ) ) )
704
+ {
705
+ None
706
+ } else {
707
+ Some ( other)
708
+ }
709
+ } )
680
710
// Get the RunCustomBuild for other lib.
681
711
. filter_map ( |other| {
682
- unit_dependencies[ & other. unit ]
712
+ state . unit_dependencies [ & other. unit ]
683
713
. iter ( )
684
714
. find ( |other_dep| other_dep. unit . mode == CompileMode :: RunCustomBuild )
685
715
. cloned ( )
@@ -695,7 +725,11 @@ fn connect_run_custom_build_deps(unit_dependencies: &mut UnitGraph) {
695
725
696
726
// And finally, add in all the missing dependencies!
697
727
for ( unit, new_deps) in new_deps {
698
- unit_dependencies. get_mut ( & unit) . unwrap ( ) . extend ( new_deps) ;
728
+ state
729
+ . unit_dependencies
730
+ . get_mut ( & unit)
731
+ . unwrap ( )
732
+ . extend ( new_deps) ;
699
733
}
700
734
}
701
735
0 commit comments