@@ -47,6 +47,11 @@ struct State<'a, 'cfg> {
4747 target_data : & ' a RustcTargetData ,
4848 profiles : & ' a Profiles ,
4949 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 ) > ,
5055}
5156
5257pub fn build_unit_dependencies < ' a , ' cfg > (
@@ -86,6 +91,7 @@ pub fn build_unit_dependencies<'a, 'cfg>(
8691 target_data,
8792 profiles,
8893 interner,
94+ dev_dependency_edges : HashSet :: new ( ) ,
8995 } ;
9096
9197 let std_unit_deps = calc_deps_of_std ( & mut state, std_roots) ?;
@@ -98,7 +104,7 @@ pub fn build_unit_dependencies<'a, 'cfg>(
98104 attach_std_deps ( & mut state, std_roots, std_unit_deps) ;
99105 }
100106
101- connect_run_custom_build_deps ( & mut state. unit_dependencies ) ;
107+ connect_run_custom_build_deps ( & mut state) ;
102108
103109 // Dependencies are used in tons of places throughout the backend, many of
104110 // which affect the determinism of the build itself. As a result be sure
@@ -258,7 +264,8 @@ fn compute_deps(
258264 } ) ;
259265
260266 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 {
262269 let pkg = state. get ( id) ;
263270 let lib = match pkg. targets ( ) . iter ( ) . find ( |t| t. is_lib ( ) ) {
264271 Some ( t) => t,
@@ -267,6 +274,7 @@ fn compute_deps(
267274 let mode = check_or_build_mode ( unit. mode , lib) ;
268275 let dep_unit_for = unit_for. with_dependency ( unit, lib) ;
269276
277+ let start = ret. len ( ) ;
270278 if state. config . cli_unstable ( ) . dual_proc_macros && lib. proc_macro ( ) && !unit. kind . is_host ( )
271279 {
272280 let unit_dep = new_unit_dep ( state, unit, pkg, lib, dep_unit_for, unit. kind , mode) ?;
@@ -286,7 +294,18 @@ fn compute_deps(
286294 ) ?;
287295 ret. push ( unit_dep) ;
288296 }
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+ }
289307 }
308+ state. dev_dependency_edges . extend ( dev_deps) ;
290309
291310 // If this target is a build script, then what we've collected so far is
292311 // 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(
617636///
618637/// Here we take the entire `deps` map and add more dependencies from execution
619638/// 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 < ' _ , ' _ > ) {
621640 let mut new_deps = Vec :: new ( ) ;
622641
623642 {
643+ let state = & * state;
624644 // First up build a reverse dependency map. This is a mapping of all
625645 // `RunCustomBuild` known steps to the unit which depends on them. For
626646 // example a library might depend on a build script, so this map will
627647 // have the build script as the key and the library would be in the
628648 // 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.
635649 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 ( ) {
640651 for dep in deps {
641652 if dep. unit . mode == CompileMode :: RunCustomBuild {
642653 reverse_deps_map
@@ -656,7 +667,8 @@ fn connect_run_custom_build_deps(unit_dependencies: &mut UnitGraph) {
656667 // `links`, then we depend on that package's build script! Here we use
657668 // `dep_build_script` to manufacture an appropriate build script unit to
658669 // depend on.
659- for unit in unit_dependencies
670+ for unit in state
671+ . unit_dependencies
660672 . keys ( )
661673 . filter ( |k| k. mode == CompileMode :: RunCustomBuild )
662674 {
@@ -670,16 +682,34 @@ fn connect_run_custom_build_deps(unit_dependencies: &mut UnitGraph) {
670682 let to_add = reverse_deps
671683 . iter ( )
672684 // 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+ } )
674690 // Only deps with `links`.
675- . filter ( |other| {
691+ . filter ( |( _parent , other) | {
676692 other. unit . pkg != unit. pkg
677693 && other. unit . target . is_linkable ( )
678694 && other. unit . pkg . manifest ( ) . links ( ) . is_some ( )
679695 } )
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+ } )
680710 // Get the RunCustomBuild for other lib.
681711 . filter_map ( |other| {
682- unit_dependencies[ & other. unit ]
712+ state . unit_dependencies [ & other. unit ]
683713 . iter ( )
684714 . find ( |other_dep| other_dep. unit . mode == CompileMode :: RunCustomBuild )
685715 . cloned ( )
@@ -695,7 +725,11 @@ fn connect_run_custom_build_deps(unit_dependencies: &mut UnitGraph) {
695725
696726 // And finally, add in all the missing dependencies!
697727 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) ;
699733 }
700734}
701735
0 commit comments