@@ -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,
@@ -270,6 +277,7 @@ fn compute_deps(
270277 // If it is a custom build script, then it *only* has build dependencies.
271278 . with_host_features ( unit. target . is_custom_build ( ) || lib. proc_macro ( ) ) ;
272279
280+ let start = ret. len ( ) ;
273281 if state. config . cli_unstable ( ) . dual_proc_macros && lib. proc_macro ( ) && !unit. kind . is_host ( )
274282 {
275283 let unit_dep = new_unit_dep ( state, unit, pkg, lib, dep_unit_for, unit. kind , mode) ?;
@@ -289,7 +297,18 @@ fn compute_deps(
289297 ) ?;
290298 ret. push ( unit_dep) ;
291299 }
300+
301+ // If the unit added was a dev-dependency unit, then record that in the
302+ // dev-dependencies array. We'll add this to
303+ // `state.dev_dependency_edges` at the end and process it later in
304+ // `connect_run_custom_build_deps`.
305+ if deps. iter ( ) . all ( |d| !d. is_transitive ( ) ) {
306+ for dep in ret[ start..] . iter ( ) {
307+ dev_deps. push ( ( unit. clone ( ) , dep. unit . clone ( ) ) ) ;
308+ }
309+ }
292310 }
311+ state. dev_dependency_edges . extend ( dev_deps) ;
293312
294313 // If this target is a build script, then what we've collected so far is
295314 // all we need. If this isn't a build script, then it depends on the
@@ -621,26 +640,18 @@ fn new_unit_dep_with_profile(
621640///
622641/// Here we take the entire `deps` map and add more dependencies from execution
623642/// of one build script to execution of another build script.
624- fn connect_run_custom_build_deps ( unit_dependencies : & mut UnitGraph ) {
643+ fn connect_run_custom_build_deps ( state : & mut State < ' _ , ' _ > ) {
625644 let mut new_deps = Vec :: new ( ) ;
626645
627646 {
647+ let state = & * state;
628648 // First up build a reverse dependency map. This is a mapping of all
629649 // `RunCustomBuild` known steps to the unit which depends on them. For
630650 // example a library might depend on a build script, so this map will
631651 // have the build script as the key and the library would be in the
632652 // value's set.
633- //
634- // Note that as an important part here we're skipping "test" units. Test
635- // units depend on the execution of a build script, but
636- // links-dependencies only propagate through `[dependencies]`, nothing
637- // else. We don't want to pull in a links-dependency through a
638- // dev-dependency since that could create a cycle.
639653 let mut reverse_deps_map = HashMap :: new ( ) ;
640- for ( unit, deps) in unit_dependencies. iter ( ) {
641- if unit. mode . is_any_test ( ) {
642- continue ;
643- }
654+ for ( unit, deps) in state. unit_dependencies . iter ( ) {
644655 for dep in deps {
645656 if dep. unit . mode == CompileMode :: RunCustomBuild {
646657 reverse_deps_map
@@ -660,7 +671,8 @@ fn connect_run_custom_build_deps(unit_dependencies: &mut UnitGraph) {
660671 // `links`, then we depend on that package's build script! Here we use
661672 // `dep_build_script` to manufacture an appropriate build script unit to
662673 // depend on.
663- for unit in unit_dependencies
674+ for unit in state
675+ . unit_dependencies
664676 . keys ( )
665677 . filter ( |k| k. mode == CompileMode :: RunCustomBuild )
666678 {
@@ -674,16 +686,34 @@ fn connect_run_custom_build_deps(unit_dependencies: &mut UnitGraph) {
674686 let to_add = reverse_deps
675687 . iter ( )
676688 // Get all sibling dependencies of `unit`
677- . flat_map ( |reverse_dep| unit_dependencies[ reverse_dep] . iter ( ) )
689+ . flat_map ( |reverse_dep| {
690+ state. unit_dependencies [ reverse_dep]
691+ . iter ( )
692+ . map ( move |a| ( reverse_dep, a) )
693+ } )
678694 // Only deps with `links`.
679- . filter ( |other| {
695+ . filter ( |( _parent , other) | {
680696 other. unit . pkg != unit. pkg
681697 && other. unit . target . is_linkable ( )
682698 && other. unit . pkg . manifest ( ) . links ( ) . is_some ( )
683699 } )
700+ // Skip dependencies induced via dev-dependencies since
701+ // connections between `links` and build scripts only happens
702+ // via normal dependencies. Otherwise since dev-dependencies can
703+ // be cyclic we could have cyclic build-script executions.
704+ . filter_map ( move |( parent, other) | {
705+ if state
706+ . dev_dependency_edges
707+ . contains ( & ( ( * parent) . clone ( ) , other. unit . clone ( ) ) )
708+ {
709+ None
710+ } else {
711+ Some ( other)
712+ }
713+ } )
684714 // Get the RunCustomBuild for other lib.
685715 . filter_map ( |other| {
686- unit_dependencies[ & other. unit ]
716+ state . unit_dependencies [ & other. unit ]
687717 . iter ( )
688718 . find ( |other_dep| other_dep. unit . mode == CompileMode :: RunCustomBuild )
689719 . cloned ( )
@@ -699,7 +729,11 @@ fn connect_run_custom_build_deps(unit_dependencies: &mut UnitGraph) {
699729
700730 // And finally, add in all the missing dependencies!
701731 for ( unit, new_deps) in new_deps {
702- unit_dependencies. get_mut ( & unit) . unwrap ( ) . extend ( new_deps) ;
732+ state
733+ . unit_dependencies
734+ . get_mut ( & unit)
735+ . unwrap ( )
736+ . extend ( new_deps) ;
703737 }
704738}
705739
0 commit comments