@@ -12,7 +12,7 @@ use jobserver::{Acquired, HelperThread};
12
12
use log:: { debug, info, trace} ;
13
13
14
14
use crate :: core:: profiles:: Profile ;
15
- use crate :: core:: { PackageId , Target , TargetKind } ;
15
+ use crate :: core:: { PackageId , Target , TargetKind , Verbosity } ;
16
16
use crate :: handle_error;
17
17
use crate :: util;
18
18
use crate :: util:: diagnostic_server:: { self , DiagnosticPrinter } ;
@@ -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,90 @@ 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
+ // CAUTION: Care must be taken to clear the progress bar if a
293
+ // message is to be actually displayed. Try to avoid
294
+ // unnecessarily clearing it to avoid flickering.
295
+ match event {
296
+ Message :: Run ( cmd) => {
297
+ if cx. bcx . config . shell ( ) . verbosity ( ) == Verbosity :: Verbose {
298
+ self . progress . clear ( ) ;
299
+ }
300
+ cx. bcx
301
+ . config
302
+ . shell ( )
303
+ . verbose ( |c| c. status ( "Running" , & cmd) ) ?;
323
304
}
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) ;
305
+ Message :: BuildPlanMsg ( module_name, cmd, filenames) => {
306
+ plan. update ( & module_name, & cmd, & filenames) ?;
307
+ }
308
+ Message :: Stdout ( out) => {
309
+ self . progress . clear ( ) ;
310
+ println ! ( "{}" , out) ;
311
+ }
312
+ Message :: Stderr ( err) => {
313
+ self . progress . clear ( ) ;
314
+ let mut shell = cx. bcx . config . shell ( ) ;
315
+ shell. print_ansi ( err. as_bytes ( ) ) ?;
316
+ shell. err ( ) . write_all ( b"\n " ) ?;
317
+ }
318
+ Message :: FixDiagnostic ( msg) => {
319
+ self . progress . clear ( ) ;
320
+ print. print ( & msg) ?;
321
+ }
322
+ Message :: Finish ( key, result) => {
323
+ info ! ( "end: {:?}" , key) ;
324
+
325
+ // self.active.remove_item(&key); // <- switch to this when stabilized.
326
+ let pos = self
327
+ . active
328
+ . iter ( )
329
+ . position ( |k| * k == key)
330
+ . expect ( "an unrecorded package has finished compiling" ) ;
331
+ self . active . remove ( pos) ;
332
+ if !self . active . is_empty ( ) {
333
+ assert ! ( !tokens. is_empty( ) ) ;
334
+ drop ( tokens. pop ( ) ) ;
335
+ }
336
+ match result {
337
+ Ok ( ( ) ) => self . finish ( key, cx) ?,
338
+ Err ( e) => {
339
+ self . progress . clear ( ) ;
340
+ let msg = "The following warnings were emitted during compilation:" ;
341
+ self . emit_warnings ( Some ( msg) , & key, cx) ?;
342
+
343
+ if !self . active . is_empty ( ) {
344
+ error = Some ( failure:: format_err!( "build failed" ) ) ;
345
+ handle_error ( & e, & mut * cx. bcx . config . shell ( ) ) ;
346
+ cx. bcx . config . shell ( ) . warn (
347
+ "build failed, waiting for other \
348
+ jobs to finish...",
349
+ ) ?;
350
+ } else {
351
+ error = Some ( e) ;
352
+ }
339
353
}
340
354
}
341
355
}
342
- }
343
- Message :: Token ( acquired_token) => {
344
- tokens. push ( acquired_token. chain_err ( || "failed to acquire jobserver token" ) ?) ;
356
+ Message :: Token ( acquired_token) => {
357
+ tokens. push (
358
+ acquired_token. chain_err ( || "failed to acquire jobserver token" ) ?,
359
+ ) ;
360
+ }
345
361
}
346
362
}
347
363
}
348
- drop ( progress) ;
364
+ self . progress . clear ( ) ;
349
365
350
366
let build_type = if self . is_release { "release" } else { "dev" } ;
351
367
// NOTE: This may be a bit inaccurate, since this may not display the
@@ -384,6 +400,19 @@ impl<'a> JobQueue<'a> {
384
400
}
385
401
}
386
402
403
+ fn show_progress ( & mut self , total : usize ) {
404
+ let count = total - self . queue . len ( ) ;
405
+ let active_names = self
406
+ . active
407
+ . iter ( )
408
+ . map ( Key :: name_for_progress)
409
+ . collect :: < Vec < _ > > ( ) ;
410
+ drop (
411
+ self . progress
412
+ . tick_now ( count, total, & format ! ( ": {}" , active_names. join( ", " ) ) ) ,
413
+ ) ;
414
+ }
415
+
387
416
/// Executes a job in the `scope` given, pushing the spawned thread's
388
417
/// handled onto `threads`.
389
418
fn run (
@@ -422,27 +451,28 @@ impl<'a> JobQueue<'a> {
422
451
}
423
452
424
453
fn emit_warnings (
425
- & self ,
454
+ & mut self ,
426
455
msg : Option < & str > ,
427
456
key : & Key < ' a > ,
428
457
cx : & mut Context < ' _ , ' _ > ,
429
458
) -> CargoResult < ( ) > {
430
459
let output = cx. build_state . outputs . lock ( ) . unwrap ( ) ;
431
460
let bcx = & mut cx. bcx ;
432
461
if let Some ( output) = output. get ( & ( key. pkg , key. kind ) ) {
433
- if let Some ( msg) = msg {
434
- if !output. warnings . is_empty ( ) {
462
+ if !output. warnings . is_empty ( ) {
463
+ self . progress . clear ( ) ;
464
+ if let Some ( msg) = msg {
435
465
writeln ! ( bcx. config. shell( ) . err( ) , "{}\n " , msg) ?;
436
466
}
437
- }
438
467
439
- for warning in output. warnings . iter ( ) {
440
- bcx. config . shell ( ) . warn ( warning) ?;
441
- }
468
+ for warning in output. warnings . iter ( ) {
469
+ bcx. config . shell ( ) . warn ( warning) ?;
470
+ }
442
471
443
- if !output. warnings . is_empty ( ) && msg. is_some ( ) {
444
- // Output an empty line.
445
- writeln ! ( bcx. config. shell( ) . err( ) ) ?;
472
+ if msg. is_some ( ) {
473
+ // Output an empty line.
474
+ writeln ! ( bcx. config. shell( ) . err( ) ) ?;
475
+ }
446
476
}
447
477
}
448
478
@@ -491,10 +521,12 @@ impl<'a> JobQueue<'a> {
491
521
// Skip Doctest
492
522
if !key. mode . is_any_test ( ) {
493
523
self . documented . insert ( key. pkg ) ;
524
+ self . progress . clear ( ) ;
494
525
config. shell ( ) . status ( "Documenting" , key. pkg ) ?;
495
526
}
496
527
} else {
497
528
self . compiled . insert ( key. pkg ) ;
529
+ self . progress . clear ( ) ;
498
530
if key. mode . is_check ( ) {
499
531
config. shell ( ) . status ( "Checking" , key. pkg ) ?;
500
532
} else {
@@ -508,6 +540,9 @@ impl<'a> JobQueue<'a> {
508
540
&& !( key. mode == CompileMode :: Doctest && self . compiled . contains ( & key. pkg ) )
509
541
{
510
542
self . compiled . insert ( key. pkg ) ;
543
+ if config. shell ( ) . verbosity ( ) == Verbosity :: Verbose {
544
+ self . progress . clear ( ) ;
545
+ }
511
546
config. shell ( ) . verbose ( |c| c. status ( "Fresh" , key. pkg ) ) ?;
512
547
}
513
548
}
0 commit comments