@@ -29,7 +29,7 @@ use super::{BuildContext, BuildPlan, CompileMode, Context, Kind, Unit};
29
29
/// This structure is backed by the `DependencyQueue` type and manages the
30
30
/// actual compilation step of each package. Packages enqueue units of work and
31
31
/// then later on the entire graph is processed and compiled.
32
- pub struct JobQueue < ' a > {
32
+ pub struct JobQueue < ' a , ' cfg > {
33
33
queue : DependencyQueue < Key < ' a > , Vec < ( Job , Freshness ) > > ,
34
34
tx : Sender < Message < ' a > > ,
35
35
rx : Receiver < Message < ' a > > ,
@@ -39,6 +39,7 @@ pub struct JobQueue<'a> {
39
39
documented : HashSet < PackageId > ,
40
40
counts : HashMap < PackageId , usize > ,
41
41
is_release : bool ,
42
+ progress : Progress < ' cfg > ,
42
43
}
43
44
44
45
/// A helper structure for metadata about the state of a building package.
@@ -131,9 +132,10 @@ impl<'a> JobState<'a> {
131
132
}
132
133
}
133
134
134
- impl < ' a > JobQueue < ' a > {
135
- pub fn new < ' cfg > ( bcx : & BuildContext < ' a , ' cfg > ) -> JobQueue < ' a > {
135
+ impl < ' a , ' cfg > JobQueue < ' a , ' cfg > {
136
+ pub fn new ( bcx : & BuildContext < ' a , ' cfg > ) -> JobQueue < ' a , ' cfg > {
136
137
let ( tx, rx) = channel ( ) ;
138
+ let progress = Progress :: with_style ( "Building" , ProgressStyle :: Ratio , bcx. config ) ;
137
139
JobQueue {
138
140
queue : DependencyQueue :: new ( ) ,
139
141
tx,
@@ -144,10 +146,11 @@ impl<'a> JobQueue<'a> {
144
146
documented : HashSet :: new ( ) ,
145
147
counts : HashMap :: new ( ) ,
146
148
is_release : bcx. build_config . release ,
149
+ progress,
147
150
}
148
151
}
149
152
150
- pub fn enqueue < ' cfg > (
153
+ pub fn enqueue (
151
154
& mut self ,
152
155
cx : & Context < ' a , ' cfg > ,
153
156
unit : & Unit < ' a > ,
@@ -231,7 +234,6 @@ impl<'a> JobQueue<'a> {
231
234
// successful and otherwise wait for pending work to finish if it failed
232
235
// and then immediately return.
233
236
let mut error = None ;
234
- let mut progress = Progress :: with_style ( "Building" , ProgressStyle :: Ratio , cx. bcx . config ) ;
235
237
let total = self . queue . len ( ) ;
236
238
loop {
237
239
// Dequeue as much work as we can, learning about everything
@@ -276,76 +278,80 @@ impl<'a> JobQueue<'a> {
276
278
// to the jobserver itself.
277
279
tokens. truncate ( self . active . len ( ) - 1 ) ;
278
280
279
- let count = total - self . queue . len ( ) ;
280
- let active_names = self
281
- . active
282
- . iter ( )
283
- . map ( Key :: name_for_progress)
284
- . collect :: < Vec < _ > > ( ) ;
285
- drop ( progress. tick_now ( count, total, & format ! ( ": {}" , active_names. join( ", " ) ) ) ) ;
286
- let event = self . rx . recv ( ) . unwrap ( ) ;
287
- progress. clear ( ) ;
288
-
289
- match event {
290
- Message :: Run ( cmd) => {
291
- cx. bcx
292
- . config
293
- . shell ( )
294
- . verbose ( |c| c. status ( "Running" , & cmd) ) ?;
295
- }
296
- Message :: BuildPlanMsg ( module_name, cmd, filenames) => {
297
- plan. update ( & module_name, & cmd, & filenames) ?;
298
- }
299
- Message :: Stdout ( out) => {
300
- println ! ( "{}" , out) ;
301
- }
302
- Message :: Stderr ( err) => {
303
- let mut shell = cx. bcx . config . shell ( ) ;
304
- shell. print_ansi ( err. as_bytes ( ) ) ?;
305
- shell. err ( ) . write_all ( b"\n " ) ?;
306
- }
307
- Message :: FixDiagnostic ( msg) => {
308
- print. print ( & msg) ?;
309
- }
310
- Message :: Finish ( key, result) => {
311
- info ! ( "end: {:?}" , key) ;
312
-
313
- // self.active.remove_item(&key); // <- switch to this when stabilized.
314
- let pos = self
315
- . active
316
- . iter ( )
317
- . position ( |k| * k == key)
318
- . expect ( "an unrecorded package has finished compiling" ) ;
319
- self . active . remove ( pos) ;
320
- if !self . active . is_empty ( ) {
321
- assert ! ( !tokens. is_empty( ) ) ;
322
- drop ( tokens. pop ( ) ) ;
281
+ // Drain all events at once to avoid displaying the progress bar
282
+ // unnecessarily.
283
+ let events: Vec < _ > = self . rx . try_iter ( ) . collect ( ) ;
284
+ let events = if events. is_empty ( ) {
285
+ self . show_progress ( total) ;
286
+ vec ! [ self . rx. recv( ) . unwrap( ) ]
287
+ } else {
288
+ events
289
+ } ;
290
+
291
+ for event in events {
292
+ match event {
293
+ Message :: Run ( cmd) => {
294
+ cx. bcx
295
+ . config
296
+ . shell ( )
297
+ . verbose ( |c| c. status ( "Running" , & cmd) ) ?;
298
+ }
299
+ Message :: BuildPlanMsg ( module_name, cmd, filenames) => {
300
+ plan. update ( & module_name, & cmd, & filenames) ?;
323
301
}
324
- match result {
325
- Ok ( ( ) ) => self . finish ( key, cx) ?,
326
- Err ( e) => {
327
- let msg = "The following warnings were emitted during compilation:" ;
328
- self . emit_warnings ( Some ( msg) , & key, cx) ?;
329
-
330
- if !self . active . is_empty ( ) {
331
- error = Some ( failure:: format_err!( "build failed" ) ) ;
332
- handle_error ( & e, & mut * cx. bcx . config . shell ( ) ) ;
333
- cx. bcx . config . shell ( ) . warn (
334
- "build failed, waiting for other \
335
- jobs to finish...",
336
- ) ?;
337
- } else {
338
- error = Some ( e) ;
302
+ Message :: Stdout ( out) => {
303
+ println ! ( "{}" , out) ;
304
+ }
305
+ Message :: Stderr ( err) => {
306
+ let mut shell = cx. bcx . config . shell ( ) ;
307
+ shell. print_ansi ( err. as_bytes ( ) ) ?;
308
+ shell. err ( ) . write_all ( b"\n " ) ?;
309
+ }
310
+ Message :: FixDiagnostic ( msg) => {
311
+ print. print ( & msg) ?;
312
+ }
313
+ Message :: Finish ( key, result) => {
314
+ info ! ( "end: {:?}" , key) ;
315
+
316
+ // self.active.remove_item(&key); // <- switch to this when stabilized.
317
+ let pos = self
318
+ . active
319
+ . iter ( )
320
+ . position ( |k| * k == key)
321
+ . expect ( "an unrecorded package has finished compiling" ) ;
322
+ self . active . remove ( pos) ;
323
+ if !self . active . is_empty ( ) {
324
+ assert ! ( !tokens. is_empty( ) ) ;
325
+ drop ( tokens. pop ( ) ) ;
326
+ }
327
+ match result {
328
+ Ok ( ( ) ) => self . finish ( key, cx) ?,
329
+ Err ( e) => {
330
+ let msg = "The following warnings were emitted during compilation:" ;
331
+ self . emit_warnings ( Some ( msg) , & key, cx) ?;
332
+
333
+ if !self . active . is_empty ( ) {
334
+ error = Some ( failure:: format_err!( "build failed" ) ) ;
335
+ handle_error ( & e, & mut * cx. bcx . config . shell ( ) ) ;
336
+ cx. bcx . config . shell ( ) . warn (
337
+ "build failed, waiting for other \
338
+ jobs to finish...",
339
+ ) ?;
340
+ } else {
341
+ error = Some ( e) ;
342
+ }
339
343
}
340
344
}
341
345
}
342
- }
343
- Message :: Token ( acquired_token) => {
344
- tokens. push ( acquired_token. chain_err ( || "failed to acquire jobserver token" ) ?) ;
346
+ Message :: Token ( acquired_token) => {
347
+ tokens. push (
348
+ acquired_token. chain_err ( || "failed to acquire jobserver token" ) ?,
349
+ ) ;
350
+ }
345
351
}
346
352
}
347
353
}
348
- drop ( progress) ;
354
+ self . progress . clear ( ) ;
349
355
350
356
let build_type = if self . is_release { "release" } else { "dev" } ;
351
357
// NOTE: This may be a bit inaccurate, since this may not display the
@@ -384,6 +390,19 @@ impl<'a> JobQueue<'a> {
384
390
}
385
391
}
386
392
393
+ fn show_progress ( & mut self , total : usize ) {
394
+ let count = total - self . queue . len ( ) ;
395
+ let active_names = self
396
+ . active
397
+ . iter ( )
398
+ . map ( Key :: name_for_progress)
399
+ . collect :: < Vec < _ > > ( ) ;
400
+ drop (
401
+ self . progress
402
+ . tick_now ( count, total, & format ! ( ": {}" , active_names. join( ", " ) ) ) ,
403
+ ) ;
404
+ }
405
+
387
406
/// Executes a job in the `scope` given, pushing the spawned thread's
388
407
/// handled onto `threads`.
389
408
fn run (
@@ -422,27 +441,27 @@ impl<'a> JobQueue<'a> {
422
441
}
423
442
424
443
fn emit_warnings (
425
- & self ,
444
+ & mut self ,
426
445
msg : Option < & str > ,
427
446
key : & Key < ' a > ,
428
447
cx : & mut Context < ' _ , ' _ > ,
429
448
) -> CargoResult < ( ) > {
430
449
let output = cx. build_state . outputs . lock ( ) . unwrap ( ) ;
431
450
let bcx = & mut cx. bcx ;
432
451
if let Some ( output) = output. get ( & ( key. pkg , key. kind ) ) {
433
- if let Some ( msg ) = msg {
434
- if !output . warnings . is_empty ( ) {
452
+ if !output . warnings . is_empty ( ) {
453
+ if let Some ( msg ) = msg {
435
454
writeln ! ( bcx. config. shell( ) . err( ) , "{}\n " , msg) ?;
436
455
}
437
- }
438
456
439
- for warning in output. warnings . iter ( ) {
440
- bcx. config . shell ( ) . warn ( warning) ?;
441
- }
457
+ for warning in output. warnings . iter ( ) {
458
+ bcx. config . shell ( ) . warn ( warning) ?;
459
+ }
442
460
443
- if !output. warnings . is_empty ( ) && msg. is_some ( ) {
444
- // Output an empty line.
445
- writeln ! ( bcx. config. shell( ) . err( ) ) ?;
461
+ if msg. is_some ( ) {
462
+ // Output an empty line.
463
+ writeln ! ( bcx. config. shell( ) . err( ) ) ?;
464
+ }
446
465
}
447
466
}
448
467
0 commit comments