8
8
// option. This file may not be copied, modified, or distributed
9
9
// except according to those terms.
10
10
11
- use serde :: { Serialize , Deserialize } ;
12
-
11
+ use std :: fmt :: Debug ;
12
+ use std :: hash :: Hash ;
13
13
use std:: cell:: RefCell ;
14
14
use std:: path:: { Path , PathBuf } ;
15
15
use std:: process:: Command ;
16
16
use std:: fs;
17
17
use std:: ops:: Deref ;
18
+ use std:: any:: { TypeId , Any } ;
18
19
19
20
use compile;
20
21
use install;
21
22
use dist;
22
23
use util:: { exe, libdir, add_lib_path} ;
23
24
use { Build , Mode } ;
24
- use cache:: { Cache , Key } ;
25
+ use cache:: { INTERNER , Interned , Cache } ;
25
26
use check;
26
27
use flags:: Subcommand ;
27
28
use doc;
@@ -34,7 +35,7 @@ pub struct Builder<'a> {
34
35
pub top_stage : u32 ,
35
36
pub kind : Kind ,
36
37
cache : Cache ,
37
- stack : RefCell < Vec < Key > > ,
38
+ stack : RefCell < Vec < ( TypeId , Box < Any > ) > > ,
38
39
}
39
40
40
41
impl < ' a > Deref for Builder < ' a > {
@@ -45,19 +46,10 @@ impl<'a> Deref for Builder<'a> {
45
46
}
46
47
}
47
48
48
- pub trait Step < ' a > : Serialize + Sized {
49
- /// The output type of this step. This is used in a few places to return a
49
+ pub trait Step : ' static + Clone + Debug + PartialEq + Eq + Hash {
50
50
/// `PathBuf` when directories are created or to return a `Compiler` once
51
51
/// it's been assembled.
52
- ///
53
- /// When possible, this should be used instead of implicitly creating files
54
- /// in a prearranged directory that will later be used by the build system.
55
- /// It's not always practical, however, since it makes avoiding rebuilds
56
- /// somewhat harder.
57
- type Output : Serialize + Deserialize < ' a > + ' a ;
58
-
59
- /// This type, but with a 'static bound. Used for caching the step.
60
- type Id : ' static ;
52
+ type Output : Clone ;
61
53
62
54
const DEFAULT : bool = false ;
63
55
@@ -72,13 +64,13 @@ pub trait Step<'a>: Serialize + Sized {
72
64
73
65
/// Primary function to execute this rule. Can call `builder.ensure(...)`
74
66
/// with other steps to run those.
75
- fn run ( self , builder : & ' a Builder ) -> Self :: Output ;
67
+ fn run ( self , builder : & Builder ) -> Self :: Output ;
76
68
77
69
/// When bootstrap is passed a set of paths, this controls whether this rule
78
70
/// will execute. However, it does not get called in a "default" context
79
71
/// when we are not passed any paths; in that case, make_run is called
80
72
/// directly.
81
- fn should_run ( _builder : & ' a Builder , _path : & Path ) -> bool { false }
73
+ fn should_run ( _builder : & Builder , _path : & Path ) -> bool { false }
82
74
83
75
/// Build up a "root" rule, either as a default rule or from a path passed
84
76
/// to us.
@@ -87,10 +79,10 @@ pub trait Step<'a>: Serialize + Sized {
87
79
/// passed. When `./x.py build` is run, for example, this rule could get
88
80
/// called if it is in the correct list below with a path of `None`.
89
81
fn make_run (
90
- _builder : & ' a Builder ,
82
+ _builder : & Builder ,
91
83
_path : Option < & Path > ,
92
- _host : & ' a str ,
93
- _target : & ' a str ,
84
+ _host : Interned < String > ,
85
+ _target : Interned < String > ,
94
86
) { unimplemented ! ( ) }
95
87
}
96
88
@@ -176,26 +168,27 @@ impl<'a> Builder<'a> {
176
168
/// not take `Compiler` since all `Compiler` instances are meant to be
177
169
/// obtained through this function, since it ensures that they are valid
178
170
/// (i.e., built and assembled).
179
- pub fn compiler ( & ' a self , stage : u32 , host : & ' a str ) -> Compiler < ' a > {
171
+ pub fn compiler ( & self , stage : u32 , host : Interned < String > ) -> Compiler {
180
172
self . ensure ( compile:: Assemble { target_compiler : Compiler { stage, host } } )
181
173
}
182
174
183
- pub fn sysroot ( & self , compiler : Compiler < ' a > ) -> PathBuf {
175
+ pub fn sysroot ( & self , compiler : Compiler ) -> Interned < PathBuf > {
184
176
self . ensure ( compile:: Sysroot { compiler } )
185
177
}
186
178
187
179
/// Returns the libdir where the standard library and other artifacts are
188
180
/// found for a compiler's sysroot.
189
- pub fn sysroot_libdir ( & self , compiler : Compiler < ' a > , target : & ' a str ) -> PathBuf {
190
- #[ derive( Serialize ) ]
191
- struct Libdir < ' a > {
192
- compiler : Compiler < ' a > ,
193
- target : & ' a str ,
181
+ pub fn sysroot_libdir (
182
+ & self , compiler : Compiler , target : Interned < String >
183
+ ) -> Interned < PathBuf > {
184
+ #[ derive( Debug , Copy , Clone , Hash , PartialEq , Eq ) ]
185
+ struct Libdir {
186
+ compiler : Compiler ,
187
+ target : Interned < String > ,
194
188
}
195
- impl < ' a > Step < ' a > for Libdir < ' a > {
196
- type Id = Libdir < ' static > ;
197
- type Output = PathBuf ;
198
- fn run ( self , builder : & Builder ) -> PathBuf {
189
+ impl Step for Libdir {
190
+ type Output = Interned < PathBuf > ;
191
+ fn run ( self , builder : & Builder ) -> Interned < PathBuf > {
199
192
let compiler = self . compiler ;
200
193
let lib = if compiler. stage >= 2 && builder. build . config . libdir_relative . is_some ( ) {
201
194
builder. build . config . libdir_relative . clone ( ) . unwrap ( )
@@ -206,7 +199,7 @@ impl<'a> Builder<'a> {
206
199
. join ( "rustlib" ) . join ( self . target ) . join ( "lib" ) ;
207
200
let _ = fs:: remove_dir_all ( & sysroot) ;
208
201
t ! ( fs:: create_dir_all( & sysroot) ) ;
209
- sysroot
202
+ INTERNER . intern_path ( sysroot)
210
203
}
211
204
}
212
205
self . ensure ( Libdir { compiler, target } )
@@ -221,7 +214,7 @@ impl<'a> Builder<'a> {
221
214
if compiler. is_snapshot ( self ) {
222
215
self . build . rustc_snapshot_libdir ( )
223
216
} else {
224
- self . sysroot ( compiler) . join ( libdir ( compiler. host ) )
217
+ self . sysroot ( compiler) . join ( libdir ( & compiler. host ) )
225
218
}
226
219
}
227
220
@@ -243,15 +236,15 @@ impl<'a> Builder<'a> {
243
236
if compiler. is_snapshot ( self ) {
244
237
self . initial_rustc . clone ( )
245
238
} else {
246
- self . sysroot ( compiler) . join ( "bin" ) . join ( exe ( "rustc" , compiler. host ) )
239
+ self . sysroot ( compiler) . join ( "bin" ) . join ( exe ( "rustc" , & compiler. host ) )
247
240
}
248
241
}
249
242
250
243
/// Get the `rustdoc` executable next to the specified compiler
251
244
pub fn rustdoc ( & self , compiler : Compiler ) -> PathBuf {
252
245
let mut rustdoc = self . rustc ( compiler) ;
253
246
rustdoc. pop ( ) ;
254
- rustdoc. push ( exe ( "rustdoc" , compiler. host ) ) ;
247
+ rustdoc. push ( exe ( "rustdoc" , & compiler. host ) ) ;
255
248
rustdoc
256
249
}
257
250
@@ -265,7 +258,7 @@ impl<'a> Builder<'a> {
265
258
pub fn cargo ( & self ,
266
259
compiler : Compiler ,
267
260
mode : Mode ,
268
- target : & str ,
261
+ target : Interned < String > ,
269
262
cmd : & str ) -> Command {
270
263
let mut cargo = Command :: new ( & self . initial_cargo ) ;
271
264
let out_dir = self . stage_out ( compiler, mode) ;
@@ -427,7 +420,7 @@ impl<'a> Builder<'a> {
427
420
cargo
428
421
}
429
422
430
- fn maybe_run < S : Step < ' a > > ( & ' a self , path : Option < & Path > ) {
423
+ fn maybe_run < S : Step > ( & self , path : Option < & Path > ) {
431
424
let build = self . build ;
432
425
let hosts = if S :: ONLY_BUILD_TARGETS || S :: ONLY_BUILD {
433
426
& build. config . host [ ..1 ]
@@ -459,41 +452,45 @@ impl<'a> Builder<'a> {
459
452
460
453
for host in hosts {
461
454
for target in targets {
462
- S :: make_run ( self , path, host, target) ;
455
+ S :: make_run ( self , path, * host, * target) ;
463
456
}
464
457
}
465
458
}
466
459
467
460
/// Ensure that a given step is built, returning it's output. This will
468
461
/// cache the step, so it is safe (and good!) to call this as often as
469
462
/// needed to ensure that all dependencies are built.
470
- pub fn ensure < S : Step < ' a > > ( & ' a self , step : S ) -> S :: Output {
471
- let key = Cache :: to_key ( & step ) ;
463
+ pub fn ensure < S : Step > ( & ' a self , step : S ) -> S :: Output {
464
+ let type_id = TypeId :: of :: < S > ( ) ;
472
465
{
473
466
let mut stack = self . stack . borrow_mut ( ) ;
474
- if stack. contains ( & key) {
467
+ for & ( stack_type_id, ref stack_step) in stack. iter ( ) {
468
+ if !( type_id == stack_type_id && step == * stack_step. downcast_ref ( ) . unwrap ( ) ) {
469
+ continue
470
+ }
475
471
let mut out = String :: new ( ) ;
476
- out += & format ! ( "\n \n Cycle in build detected when adding {:?}\n " , key ) ;
472
+ out += & format ! ( "\n \n Cycle in build detected when adding {:?}\n " , step ) ;
477
473
for el in stack. iter ( ) . rev ( ) {
478
474
out += & format ! ( "\t {:?}\n " , el) ;
479
475
}
480
476
panic ! ( out) ;
481
477
}
482
- if let Some ( out) = self . cache . get :: < S :: Output > ( & key ) {
483
- self . build . verbose ( & format ! ( "{}c {:?}" , " " . repeat( stack. len( ) ) , key ) ) ;
478
+ if let Some ( out) = self . cache . get ( & step ) {
479
+ self . build . verbose ( & format ! ( "{}c {:?}" , " " . repeat( stack. len( ) ) , step ) ) ;
484
480
485
481
return out;
486
482
}
487
- self . build . verbose ( & format ! ( "{}> {:?}" , " " . repeat( stack. len( ) ) , key ) ) ;
488
- stack. push ( key . clone ( ) ) ;
483
+ self . build . verbose ( & format ! ( "{}> {:?}" , " " . repeat( stack. len( ) ) , step ) ) ;
484
+ stack. push ( ( type_id , Box :: new ( step . clone ( ) ) ) ) ;
489
485
}
490
- let out = step. run ( self ) ;
486
+ let out = step. clone ( ) . run ( self ) ;
491
487
{
492
488
let mut stack = self . stack . borrow_mut ( ) ;
493
- assert_eq ! ( stack. pop( ) . as_ref( ) , Some ( & key) ) ;
489
+ let ( cur_type_id, cur_step) = stack. pop ( ) . expect ( "step stack empty" ) ;
490
+ assert_eq ! ( ( cur_type_id, cur_step. downcast_ref( ) ) , ( type_id, Some ( & step) ) ) ;
494
491
}
495
- self . build . verbose ( & format ! ( "{}< {:?}" , " " . repeat( self . stack. borrow( ) . len( ) ) , key ) ) ;
496
- self . cache . put ( key . clone ( ) , & out ) ;
497
- self . cache . get :: < S :: Output > ( & key ) . unwrap ( )
492
+ self . build . verbose ( & format ! ( "{}< {:?}" , " " . repeat( self . stack. borrow( ) . len( ) ) , step ) ) ;
493
+ self . cache . put ( step , out . clone ( ) ) ;
494
+ out
498
495
}
499
496
}
0 commit comments