1
1
use std:: any:: { Any , type_name} ;
2
- use std:: cell:: { Cell , RefCell } ;
2
+ use std:: cell:: Cell ;
3
3
use std:: collections:: BTreeSet ;
4
4
use std:: fmt:: { self , Debug , Write } ;
5
5
use std:: hash:: Hash ;
6
6
use std:: ops:: Deref ;
7
7
use std:: path:: { Path , PathBuf } ;
8
- use std:: sync:: { LazyLock , OnceLock } ;
8
+ use std:: sync:: { Arc , LazyLock , Mutex , OnceLock } ;
9
9
use std:: time:: { Duration , Instant } ;
10
10
use std:: { env, fs} ;
11
11
@@ -32,6 +32,25 @@ mod cargo;
32
32
#[ cfg( test) ]
33
33
mod tests;
34
34
35
+ type StepStack = Arc < Mutex < Vec < Box < dyn AnyDebug > > > > ;
36
+
37
+ /// Pointer to the active step stack of the currently executing `Builder`.
38
+ static ACTIVE_BUILDER_STEP_STACK : Mutex < Option < StepStack > > = Mutex :: new ( None ) ;
39
+
40
+ /// Prints the current contents of the active builder's step stack.
41
+ fn print_step_stack ( ) {
42
+ if let Ok ( stack) = ACTIVE_BUILDER_STEP_STACK . try_lock ( )
43
+ && let Some ( ref stack) = * stack
44
+ && let Ok ( stack) = stack. try_lock ( )
45
+ {
46
+ eprintln ! ( "\n ---BOOTSTRAP step stack start---\n " ) ;
47
+ for step in & * stack {
48
+ eprintln ! ( "{step:?}" ) ;
49
+ }
50
+ eprintln ! ( "\n ---BOOTSTRAP step stack end---\n " ) ;
51
+ }
52
+ }
53
+
35
54
/// Builds and performs different [`Self::kind`]s of stuff and actions, taking
36
55
/// into account build configuration from e.g. bootstrap.toml.
37
56
pub struct Builder < ' a > {
@@ -52,7 +71,7 @@ pub struct Builder<'a> {
52
71
53
72
/// A stack of [`Step`]s to run before we can run this builder. The output
54
73
/// of steps is cached in [`Self::cache`].
55
- stack : RefCell < Vec < Box < dyn AnyDebug > > > ,
74
+ stack : StepStack ,
56
75
57
76
/// The total amount of time we spent running [`Step`]s in [`Self::stack`].
58
77
time_spent_on_dependencies : Cell < Duration > ,
@@ -78,8 +97,8 @@ impl Deref for Builder<'_> {
78
97
/// type's [`Debug`] implementation.
79
98
///
80
99
/// (Trying to debug-print `dyn Any` results in the unhelpful `"Any { .. }"`.)
81
- pub trait AnyDebug : Any + Debug { }
82
- impl < T : Any + Debug > AnyDebug for T { }
100
+ pub trait AnyDebug : Any + Debug + Send { }
101
+ impl < T : Any + Debug + Send > AnyDebug for T { }
83
102
impl dyn AnyDebug {
84
103
/// Equivalent to `<dyn Any>::downcast_ref`.
85
104
fn downcast_ref < T : Any > ( & self ) -> Option < & T > {
@@ -89,7 +108,7 @@ impl dyn AnyDebug {
89
108
// Feel free to add other `dyn Any` methods as necessary.
90
109
}
91
110
92
- pub trait Step : ' static + Clone + Debug + PartialEq + Eq + Hash {
111
+ pub trait Step : ' static + Clone + Debug + PartialEq + Eq + Hash + Send {
93
112
/// Result type of `Step::run`.
94
113
type Output : Clone ;
95
114
@@ -1265,12 +1284,20 @@ impl<'a> Builder<'a> {
1265
1284
}
1266
1285
1267
1286
fn new_internal ( build : & Build , kind : Kind , paths : Vec < PathBuf > ) -> Builder < ' _ > {
1287
+ let stack = Arc :: new ( Mutex :: new ( Vec :: new ( ) ) ) ;
1288
+
1289
+ // Store the current step stack
1290
+ * ACTIVE_BUILDER_STEP_STACK . lock ( ) . unwrap ( ) = Some ( stack. clone ( ) ) ;
1291
+
1292
+ // And configure `build_helper` to print it on exit
1293
+ * build_helper:: util:: EXIT_CONTEXT . lock ( ) . unwrap ( ) = Some ( print_step_stack) ;
1294
+
1268
1295
Builder {
1269
1296
build,
1270
1297
top_stage : build. config . stage ,
1271
1298
kind,
1272
1299
cache : Cache :: new ( ) ,
1273
- stack : RefCell :: new ( Vec :: new ( ) ) ,
1300
+ stack,
1274
1301
time_spent_on_dependencies : Cell :: new ( Duration :: new ( 0 , 0 ) ) ,
1275
1302
paths,
1276
1303
submodule_paths_cache : Default :: default ( ) ,
@@ -1673,9 +1700,9 @@ You have to build a stage1 compiler for `{}` first, and then use it to build a s
1673
1700
/// Ensure that a given step is built, returning its output. This will
1674
1701
/// cache the step, so it is safe (and good!) to call this as often as
1675
1702
/// needed to ensure that all dependencies are built.
1676
- pub fn ensure < S : Step > ( & ' a self , step : S ) -> S :: Output {
1703
+ pub fn ensure < S : Step + Send > ( & ' a self , step : S ) -> S :: Output {
1677
1704
{
1678
- let mut stack = self . stack . borrow_mut ( ) ;
1705
+ let mut stack = self . stack . lock ( ) . unwrap ( ) ;
1679
1706
for stack_step in stack. iter ( ) {
1680
1707
// should skip
1681
1708
if stack_step. downcast_ref :: < S > ( ) . is_none_or ( |stack_step| * stack_step != step) {
@@ -1754,7 +1781,7 @@ You have to build a stage1 compiler for `{}` first, and then use it to build a s
1754
1781
self . metrics . exit_step ( self ) ;
1755
1782
1756
1783
{
1757
- let mut stack = self . stack . borrow_mut ( ) ;
1784
+ let mut stack = self . stack . lock ( ) . unwrap ( ) ;
1758
1785
let cur_step = stack. pop ( ) . expect ( "step stack empty" ) ;
1759
1786
assert_eq ! ( cur_step. downcast_ref( ) , Some ( & step) ) ;
1760
1787
}
0 commit comments