1515//! (for example, with and without tests), so we actually build a dependency
1616//! graph of `Unit`s, which capture these properties.
1717
18- use std:: cell:: RefCell ;
19- use std:: collections:: { HashMap , HashSet } ;
20-
21- use log:: trace;
22-
23- use super :: { BuildContext , CompileMode , Kind } ;
2418use crate :: core:: compiler:: Unit ;
19+ use crate :: core:: compiler:: { BuildContext , CompileMode , Context , Kind } ;
2520use crate :: core:: dependency:: Kind as DepKind ;
2621use crate :: core:: package:: Downloads ;
2722use crate :: core:: profiles:: UnitFor ;
2823use crate :: core:: { Package , PackageId , Target } ;
2924use crate :: CargoResult ;
25+ use log:: trace;
26+ use std:: collections:: { HashMap , HashSet } ;
3027
3128struct State < ' a : ' tmp , ' cfg : ' a , ' tmp > {
32- bcx : & ' tmp BuildContext < ' a , ' cfg > ,
33- deps : & ' tmp mut HashMap < Unit < ' a > , Vec < Unit < ' a > > > ,
34- pkgs : RefCell < & ' tmp mut HashMap < PackageId , & ' a Package > > ,
29+ cx : & ' tmp mut Context < ' a , ' cfg > ,
3530 waiting_on_download : HashSet < PackageId > ,
3631 downloads : Downloads < ' a , ' cfg > ,
3732}
3833
3934pub fn build_unit_dependencies < ' a , ' cfg > (
35+ cx : & mut Context < ' a , ' cfg > ,
4036 roots : & [ Unit < ' a > ] ,
41- bcx : & BuildContext < ' a , ' cfg > ,
42- deps : & mut HashMap < Unit < ' a > , Vec < Unit < ' a > > > ,
43- pkgs : & mut HashMap < PackageId , & ' a Package > ,
4437) -> CargoResult < ( ) > {
45- assert ! ( deps. is_empty( ) , "can only build unit deps once" ) ;
38+ assert ! (
39+ cx. unit_dependencies. is_empty( ) ,
40+ "can only build unit deps once"
41+ ) ;
4642
4743 let mut state = State {
48- bcx,
49- deps,
50- pkgs : RefCell :: new ( pkgs) ,
44+ downloads : cx. bcx . packages . enable_download ( ) ?,
45+ cx,
5146 waiting_on_download : HashSet :: new ( ) ,
52- downloads : bcx. packages . enable_download ( ) ?,
5347 } ;
5448
5549 loop {
@@ -62,7 +56,7 @@ pub fn build_unit_dependencies<'a, 'cfg>(
6256 // cleared, and avoid building the lib thrice (once with `panic`, once
6357 // without, once for `--test`). In particular, the lib included for
6458 // Doc tests and examples are `Build` mode here.
65- let unit_for = if unit. mode . is_any_test ( ) || bcx. build_config . test ( ) {
59+ let unit_for = if unit. mode . is_any_test ( ) || state . cx . bcx . build_config . test ( ) {
6660 UnitFor :: new_test ( )
6761 } else if unit. target . is_custom_build ( ) {
6862 // This normally doesn't happen, except `clean` aggressively
@@ -79,20 +73,23 @@ pub fn build_unit_dependencies<'a, 'cfg>(
7973
8074 if !state. waiting_on_download . is_empty ( ) {
8175 state. finish_some_downloads ( ) ?;
82- state. deps . clear ( ) ;
76+ state. cx . unit_dependencies . clear ( ) ;
8377 } else {
8478 break ;
8579 }
8680 }
87- trace ! ( "ALL UNIT DEPENDENCIES {:#?}" , state. deps) ;
8881
8982 connect_run_custom_build_deps ( & mut state) ;
9083
84+ trace ! ( "ALL UNIT DEPENDENCIES {:#?}" , state. cx. unit_dependencies) ;
85+
86+ record_units_requiring_metadata ( state. cx ) ;
87+
9188 // Dependencies are used in tons of places throughout the backend, many of
9289 // which affect the determinism of the build itself. As a result be sure
9390 // that dependency lists are always sorted to ensure we've always got a
9491 // deterministic output.
95- for list in state. deps . values_mut ( ) {
92+ for list in state. cx . unit_dependencies . values_mut ( ) {
9693 list. sort ( ) ;
9794 }
9895
@@ -104,16 +101,16 @@ fn deps_of<'a, 'cfg, 'tmp>(
104101 state : & mut State < ' a , ' cfg , ' tmp > ,
105102 unit_for : UnitFor ,
106103) -> CargoResult < ( ) > {
107- // Currently the `deps ` map does not include `unit_for`. This should
104+ // Currently the `unit_dependencies ` map does not include `unit_for`. This should
108105 // be safe for now. `TestDependency` only exists to clear the `panic`
109106 // flag, and you'll never ask for a `unit` with `panic` set as a
110107 // `TestDependency`. `CustomBuild` should also be fine since if the
111108 // requested unit's settings are the same as `Any`, `CustomBuild` can't
112109 // affect anything else in the hierarchy.
113- if !state. deps . contains_key ( unit) {
110+ if !state. cx . unit_dependencies . contains_key ( unit) {
114111 let unit_deps = compute_deps ( unit, state, unit_for) ?;
115112 let to_insert: Vec < _ > = unit_deps. iter ( ) . map ( |& ( unit, _) | unit) . collect ( ) ;
116- state. deps . insert ( * unit, to_insert) ;
113+ state. cx . unit_dependencies . insert ( * unit, to_insert) ;
117114 for ( unit, unit_for) in unit_deps {
118115 deps_of ( & unit, state, unit_for) ?;
119116 }
@@ -131,13 +128,13 @@ fn compute_deps<'a, 'cfg, 'tmp>(
131128 unit_for : UnitFor ,
132129) -> CargoResult < Vec < ( Unit < ' a > , UnitFor ) > > {
133130 if unit. mode . is_run_custom_build ( ) {
134- return compute_deps_custom_build ( unit, state. bcx ) ;
131+ return compute_deps_custom_build ( unit, state. cx . bcx ) ;
135132 } else if unit. mode . is_doc ( ) && !unit. mode . is_any_test ( ) {
136133 // Note: this does not include doc test.
137134 return compute_deps_doc ( unit, state) ;
138135 }
139136
140- let bcx = state. bcx ;
137+ let bcx = state. cx . bcx ;
141138 let id = unit. pkg . package_id ( ) ;
142139 let deps = bcx. resolve . deps ( id) . filter ( |& ( _id, deps) | {
143140 assert ! ( !deps. is_empty( ) ) ;
@@ -295,7 +292,7 @@ fn compute_deps_doc<'a, 'cfg, 'tmp>(
295292 unit : & Unit < ' a > ,
296293 state : & mut State < ' a , ' cfg , ' tmp > ,
297294) -> CargoResult < Vec < ( Unit < ' a > , UnitFor ) > > {
298- let bcx = state. bcx ;
295+ let bcx = state. cx . bcx ;
299296 let deps = bcx
300297 . resolve
301298 . deps ( unit. pkg . package_id ( ) )
@@ -448,7 +445,7 @@ fn connect_run_custom_build_deps(state: &mut State<'_, '_, '_>) {
448445 // have the build script as the key and the library would be in the
449446 // value's set.
450447 let mut reverse_deps = HashMap :: new ( ) ;
451- for ( unit, deps) in state. deps . iter ( ) {
448+ for ( unit, deps) in state. cx . unit_dependencies . iter ( ) {
452449 for dep in deps {
453450 if dep. mode == CompileMode :: RunCustomBuild {
454451 reverse_deps
@@ -469,7 +466,8 @@ fn connect_run_custom_build_deps(state: &mut State<'_, '_, '_>) {
469466 // `dep_build_script` to manufacture an appropriate build script unit to
470467 // depend on.
471468 for unit in state
472- . deps
469+ . cx
470+ . unit_dependencies
473471 . keys ( )
474472 . filter ( |k| k. mode == CompileMode :: RunCustomBuild )
475473 {
@@ -480,13 +478,13 @@ fn connect_run_custom_build_deps(state: &mut State<'_, '_, '_>) {
480478
481479 let to_add = reverse_deps
482480 . iter ( )
483- . flat_map ( |reverse_dep| state. deps [ reverse_dep] . iter ( ) )
481+ . flat_map ( |reverse_dep| state. cx . unit_dependencies [ reverse_dep] . iter ( ) )
484482 . filter ( |other| {
485483 other. pkg != unit. pkg
486484 && other. target . linkable ( )
487485 && other. pkg . manifest ( ) . links ( ) . is_some ( )
488486 } )
489- . filter_map ( |other| dep_build_script ( other, state. bcx ) . map ( |p| p. 0 ) )
487+ . filter_map ( |other| dep_build_script ( other, state. cx . bcx ) . map ( |p| p. 0 ) )
490488 . collect :: < HashSet < _ > > ( ) ;
491489
492490 if !to_add. is_empty ( ) {
@@ -497,21 +495,39 @@ fn connect_run_custom_build_deps(state: &mut State<'_, '_, '_>) {
497495
498496 // And finally, add in all the missing dependencies!
499497 for ( unit, new_deps) in new_deps {
500- state. deps . get_mut ( & unit) . unwrap ( ) . extend ( new_deps) ;
498+ state
499+ . cx
500+ . unit_dependencies
501+ . get_mut ( & unit)
502+ . unwrap ( )
503+ . extend ( new_deps) ;
504+ }
505+ }
506+
507+ /// Records the list of units which are required to emit metadata.
508+ ///
509+ /// Units which depend only on the metadata of others requires the others to
510+ /// actually produce metadata, so we'll record that here.
511+ fn record_units_requiring_metadata ( cx : & mut Context < ' _ , ' _ > ) {
512+ for ( key, deps) in cx. unit_dependencies . iter ( ) {
513+ for dep in deps {
514+ if cx. only_requires_rmeta ( key, dep) {
515+ cx. rmeta_required . insert ( * dep) ;
516+ }
517+ }
501518 }
502519}
503520
504521impl < ' a , ' cfg , ' tmp > State < ' a , ' cfg , ' tmp > {
505522 fn get ( & mut self , id : PackageId ) -> CargoResult < Option < & ' a Package > > {
506- let mut pkgs = self . pkgs . borrow_mut ( ) ;
507- if let Some ( pkg) = pkgs. get ( & id) {
523+ if let Some ( pkg) = self . cx . package_cache . get ( & id) {
508524 return Ok ( Some ( pkg) ) ;
509525 }
510526 if !self . waiting_on_download . insert ( id) {
511527 return Ok ( None ) ;
512528 }
513529 if let Some ( pkg) = self . downloads . start ( id) ? {
514- pkgs . insert ( id, pkg) ;
530+ self . cx . package_cache . insert ( id, pkg) ;
515531 self . waiting_on_download . remove ( & id) ;
516532 return Ok ( Some ( pkg) ) ;
517533 }
@@ -531,7 +547,7 @@ impl<'a, 'cfg, 'tmp> State<'a, 'cfg, 'tmp> {
531547 loop {
532548 let pkg = self . downloads . wait ( ) ?;
533549 self . waiting_on_download . remove ( & pkg. package_id ( ) ) ;
534- self . pkgs . borrow_mut ( ) . insert ( pkg. package_id ( ) , pkg) ;
550+ self . cx . package_cache . insert ( pkg. package_id ( ) , pkg) ;
535551
536552 // Arbitrarily choose that 5 or more packages concurrently download
537553 // is a good enough number to "fill the network pipe". If we have
0 commit comments