@@ -19,14 +19,16 @@ use super::{BuildContext, CompileMode, Kind, Unit};
1919use core:: dependency:: Kind as DepKind ;
2020use core:: profiles:: ProfileFor ;
2121use core:: { Package , Target } ;
22- use std:: collections:: HashMap ;
22+ use std:: collections:: { HashMap , HashSet } ;
2323use CargoResult ;
2424
2525pub fn build_unit_dependencies < ' a , ' cfg > (
2626 roots : & [ Unit < ' a > ] ,
2727 bcx : & BuildContext < ' a , ' cfg > ,
28- mut deps : & mut HashMap < Unit < ' a > , Vec < Unit < ' a > > > ,
28+ deps : & mut HashMap < Unit < ' a > , Vec < Unit < ' a > > > ,
2929) -> CargoResult < ( ) > {
30+ assert ! ( deps. len( ) == 0 , "can only build unit deps once" ) ;
31+
3032 for unit in roots. iter ( ) {
3133 // Dependencies of tests/benches should not have `panic` set.
3234 // We check the global test mode to see if we are running in `cargo
@@ -39,33 +41,35 @@ pub fn build_unit_dependencies<'a, 'cfg>(
3941 } else {
4042 ProfileFor :: Any
4143 } ;
42- deps_of ( unit, bcx, & mut deps, profile_for) ?;
44+ deps_of ( unit, bcx, deps, profile_for) ?;
4345 }
4446
47+ connect_run_custom_build_deps ( bcx, deps) ;
48+
4549 Ok ( ( ) )
4650}
4751
48- fn deps_of < ' a , ' b , ' cfg > (
52+ fn deps_of < ' a , ' cfg > (
4953 unit : & Unit < ' a > ,
5054 bcx : & BuildContext < ' a , ' cfg > ,
51- deps : & ' b mut HashMap < Unit < ' a > , Vec < Unit < ' a > > > ,
55+ deps : & mut HashMap < Unit < ' a > , Vec < Unit < ' a > > > ,
5256 profile_for : ProfileFor ,
53- ) -> CargoResult < & ' b [ Unit < ' a > ] > {
57+ ) -> CargoResult < ( ) > {
5458 // Currently the `deps` map does not include `profile_for`. This should
5559 // be safe for now. `TestDependency` only exists to clear the `panic`
5660 // flag, and you'll never ask for a `unit` with `panic` set as a
5761 // `TestDependency`. `CustomBuild` should also be fine since if the
5862 // requested unit's settings are the same as `Any`, `CustomBuild` can't
5963 // affect anything else in the hierarchy.
6064 if !deps. contains_key ( unit) {
61- let unit_deps = compute_deps ( unit, bcx, deps , profile_for) ?;
65+ let unit_deps = compute_deps ( unit, bcx, profile_for) ?;
6266 let to_insert: Vec < _ > = unit_deps. iter ( ) . map ( |& ( unit, _) | unit) . collect ( ) ;
6367 deps. insert ( * unit, to_insert) ;
6468 for ( unit, profile_for) in unit_deps {
6569 deps_of ( & unit, bcx, deps, profile_for) ?;
6670 }
6771 }
68- Ok ( deps [ unit ] . as_ref ( ) )
72+ Ok ( ( ) )
6973}
7074
7175/// For a package, return all targets which are registered as dependencies
@@ -75,11 +79,10 @@ fn deps_of<'a, 'b, 'cfg>(
7579fn compute_deps < ' a , ' b , ' cfg > (
7680 unit : & Unit < ' a > ,
7781 bcx : & BuildContext < ' a , ' cfg > ,
78- deps : & ' b mut HashMap < Unit < ' a > , Vec < Unit < ' a > > > ,
7982 profile_for : ProfileFor ,
8083) -> CargoResult < Vec < ( Unit < ' a > , ProfileFor ) > > {
8184 if unit. mode . is_run_custom_build ( ) {
82- return compute_deps_custom_build ( unit, bcx, deps ) ;
85+ return compute_deps_custom_build ( unit, bcx) ;
8386 } else if unit. mode . is_doc ( ) && !unit. mode . is_any_test ( ) {
8487 // Note: This does not include Doctest.
8588 return compute_deps_doc ( unit, bcx) ;
@@ -192,39 +195,27 @@ fn compute_deps<'a, 'b, 'cfg>(
192195fn compute_deps_custom_build < ' a , ' cfg > (
193196 unit : & Unit < ' a > ,
194197 bcx : & BuildContext < ' a , ' cfg > ,
195- deps : & mut HashMap < Unit < ' a > , Vec < Unit < ' a > > > ,
196198) -> CargoResult < Vec < ( Unit < ' a > , ProfileFor ) > > {
197199 // When not overridden, then the dependencies to run a build script are:
198200 //
199201 // 1. Compiling the build script itself
200202 // 2. For each immediate dependency of our package which has a `links`
201203 // key, the execution of that build script.
202- let deps = deps
203- . iter ( )
204- . find ( |( key, _deps) | key. pkg == unit. pkg && !key. target . is_custom_build ( ) )
205- . expect ( "can't find package deps" )
206- . 1 ;
207- Ok ( deps. iter ( )
208- . filter_map ( |unit| {
209- if !unit. target . linkable ( ) || unit. pkg . manifest ( ) . links ( ) . is_none ( ) {
210- return None ;
211- }
212- dep_build_script ( unit, bcx)
213- } )
214- . chain ( Some ( (
215- new_unit (
216- bcx,
217- unit. pkg ,
218- unit. target ,
219- ProfileFor :: CustomBuild ,
220- Kind :: Host , // build scripts always compiled for the host
221- CompileMode :: Build ,
222- ) ,
223- // All dependencies of this unit should use profiles for custom
224- // builds.
225- ProfileFor :: CustomBuild ,
226- ) ) )
227- . collect ( ) )
204+ //
205+ // We don't have a great way of handling (2) here right now so this is
206+ // deferred until after the graph of all unit dependencies has been
207+ // constructed.
208+ let unit = new_unit (
209+ bcx,
210+ unit. pkg ,
211+ unit. target ,
212+ ProfileFor :: CustomBuild ,
213+ Kind :: Host , // build scripts always compiled for the host
214+ CompileMode :: Build ,
215+ ) ;
216+ // All dependencies of this unit should use profiles for custom
217+ // builds.
218+ Ok ( vec ! [ ( unit, ProfileFor :: CustomBuild ) ] )
228219}
229220
230221/// Returns the dependencies necessary to document a package
@@ -369,3 +360,74 @@ fn new_unit<'a>(
369360 mode,
370361 }
371362}
363+
364+ /// Fill in missing dependencies for units of the `RunCustomBuild`
365+ ///
366+ /// As mentioned above in `compute_deps_custom_build` each build script
367+ /// execution has two dependencies. The first is compiling the build script
368+ /// itself (already added) and the second is that all crates the package of the
369+ /// build script depends on with `links` keys, their build script execution. (a
370+ /// bit confusing eh?)
371+ ///
372+ /// Here we take the entire `deps` map and add more dependencies from execution
373+ /// of one build script to execution of another build script.
374+ fn connect_run_custom_build_deps < ' a > (
375+ bcx : & BuildContext ,
376+ deps : & mut HashMap < Unit < ' a > , Vec < Unit < ' a > > > ,
377+ ) {
378+ let mut new_deps = Vec :: new ( ) ;
379+
380+ {
381+ // First up build a reverse dependency map. This is a mapping of all
382+ // `RunCustomBuild` known steps to the unit which depends on them. For
383+ // example a library might depend on a build script, so this map will
384+ // have the build script as the key and the library would be in the
385+ // value's set.
386+ let mut reverse_deps = HashMap :: new ( ) ;
387+ for ( unit, deps) in deps. iter ( ) {
388+ for dep in deps {
389+ if dep. mode == CompileMode :: RunCustomBuild {
390+ reverse_deps. entry ( dep)
391+ . or_insert ( HashSet :: new ( ) )
392+ . insert ( unit) ;
393+ }
394+ }
395+ }
396+
397+ // And next we take a look at all build scripts executions listed in the
398+ // dependency map. Our job here is to take everything that depends on
399+ // this build script (from our reverse map above) and look at the other
400+ // package dependencies of these parents.
401+ //
402+ // If we depend on a linkable target and the build script mentions
403+ // `links`, then we depend on that package's build script! Here we use
404+ // `dep_build_script` to manufacture an appropriate build script unit to
405+ // depend on.
406+ for unit in deps. keys ( ) . filter ( |k| k. mode == CompileMode :: RunCustomBuild ) {
407+ let reverse_deps = match reverse_deps. get ( unit) {
408+ Some ( set) => set,
409+ None => continue ,
410+ } ;
411+
412+ let to_add = reverse_deps
413+ . iter ( )
414+ . flat_map ( |reverse_dep| deps[ reverse_dep] . iter ( ) )
415+ . filter ( |other| {
416+ other. pkg != unit. pkg &&
417+ other. target . linkable ( ) &&
418+ other. pkg . manifest ( ) . links ( ) . is_some ( )
419+ } )
420+ . filter_map ( |other| dep_build_script ( other, bcx) . map ( |p| p. 0 ) )
421+ . collect :: < HashSet < _ > > ( ) ;
422+
423+ if !to_add. is_empty ( ) {
424+ new_deps. push ( ( * unit, to_add) ) ;
425+ }
426+ }
427+ }
428+
429+ // And finally, add in all the missing dependencies!
430+ for ( unit, new_deps) in new_deps {
431+ deps. get_mut ( & unit) . unwrap ( ) . extend ( new_deps) ;
432+ }
433+ }
0 commit comments