@@ -14,6 +14,7 @@ use core::{PackageId, Target};
14
14
use handle_error;
15
15
use util:: { internal, profile, CargoResult , CargoResultExt , ProcessBuilder } ;
16
16
use util:: { Config , DependencyQueue , Dirty , Fresh , Freshness } ;
17
+ use util:: { Progress , ProgressStyle } ;
17
18
18
19
use super :: job:: Job ;
19
20
use super :: { BuildContext , BuildPlan , CompileMode , Context , Kind , Unit } ;
@@ -28,7 +29,7 @@ pub struct JobQueue<'a> {
28
29
queue : DependencyQueue < Key < ' a > , Vec < ( Job , Freshness ) > > ,
29
30
tx : Sender < Message < ' a > > ,
30
31
rx : Receiver < Message < ' a > > ,
31
- active : usize ,
32
+ active : Vec < Key < ' a > > ,
32
33
pending : HashMap < Key < ' a > , PendingBuild > ,
33
34
compiled : HashSet < & ' a PackageId > ,
34
35
documented : HashSet < & ' a PackageId > ,
@@ -98,7 +99,7 @@ impl<'a> JobQueue<'a> {
98
99
queue : DependencyQueue :: new ( ) ,
99
100
tx,
100
101
rx,
101
- active : 0 ,
102
+ active : Vec :: new ( ) ,
102
103
pending : HashMap :: new ( ) ,
103
104
compiled : HashSet :: new ( ) ,
104
105
documented : HashSet :: new ( ) ,
@@ -180,6 +181,8 @@ impl<'a> JobQueue<'a> {
180
181
// successful and otherwise wait for pending work to finish if it failed
181
182
// and then immediately return.
182
183
let mut error = None ;
184
+ let mut progress = Progress :: with_style ( "Building" , ProgressStyle :: Ratio , cx. bcx . config ) ;
185
+ let total = self . queue . len ( ) ;
183
186
loop {
184
187
// Dequeue as much work as we can, learning about everything
185
188
// possible that can run. Note that this is also the point where we
@@ -196,7 +199,7 @@ impl<'a> JobQueue<'a> {
196
199
) ;
197
200
for ( job, f) in jobs {
198
201
queue. push ( ( key, job, f. combine ( fresh) ) ) ;
199
- if self . active + queue. len ( ) > 0 {
202
+ if ! self . active . is_empty ( ) || ! queue. is_empty ( ) {
200
203
jobserver_helper. request_token ( ) ;
201
204
}
202
205
}
@@ -205,14 +208,14 @@ impl<'a> JobQueue<'a> {
205
208
// Now that we've learned of all possible work that we can execute
206
209
// try to spawn it so long as we've got a jobserver token which says
207
210
// we're able to perform some parallel work.
208
- while error. is_none ( ) && self . active < tokens. len ( ) + 1 && !queue. is_empty ( ) {
211
+ while error. is_none ( ) && self . active . len ( ) < tokens. len ( ) + 1 && !queue. is_empty ( ) {
209
212
let ( key, job, fresh) = queue. remove ( 0 ) ;
210
213
self . run ( key, fresh, job, cx. bcx . config , scope, build_plan) ?;
211
214
}
212
215
213
216
// If after all that we're not actually running anything then we're
214
217
// done!
215
- if self . active == 0 {
218
+ if self . active . is_empty ( ) {
216
219
break ;
217
220
}
218
221
@@ -221,9 +224,18 @@ impl<'a> JobQueue<'a> {
221
224
// jobserver interface is architected we may acquire a token that we
222
225
// don't actually use, and if this happens just relinquish it back
223
226
// to the jobserver itself.
224
- tokens. truncate ( self . active - 1 ) ;
225
-
226
- match self . rx . recv ( ) . unwrap ( ) {
227
+ tokens. truncate ( self . active . len ( ) - 1 ) ;
228
+
229
+ let count = total - self . queue . len ( ) ;
230
+ let active_names = self . active . iter ( ) . map ( |key| match key. mode {
231
+ CompileMode :: Doc { .. } => format ! ( "{}(doc)" , key. pkg. name( ) ) ,
232
+ _ => key. pkg . name ( ) . to_string ( ) ,
233
+ } ) . collect :: < Vec < _ > > ( ) ;
234
+ drop ( progress. tick_now ( count, total, & format ! ( ": {}" , active_names. join( ", " ) ) ) ) ;
235
+ let event = self . rx . recv ( ) . unwrap ( ) ;
236
+ progress. clear ( ) ;
237
+
238
+ match event {
227
239
Message :: Run ( cmd) => {
228
240
cx. bcx
229
241
. config
@@ -245,8 +257,15 @@ impl<'a> JobQueue<'a> {
245
257
}
246
258
Message :: Finish ( key, result) => {
247
259
info ! ( "end: {:?}" , key) ;
248
- self . active -= 1 ;
249
- if self . active > 0 {
260
+
261
+ // self.active.remove_item(&key); // <- switch to this when stabilized.
262
+ let pos = self
263
+ . active
264
+ . iter ( )
265
+ . position ( |k| * k == key)
266
+ . expect ( "an unrecorded package has finished compiling" ) ;
267
+ self . active . remove ( pos) ;
268
+ if !self . active . is_empty ( ) {
250
269
assert ! ( !tokens. is_empty( ) ) ;
251
270
drop ( tokens. pop ( ) ) ;
252
271
}
@@ -256,7 +275,7 @@ impl<'a> JobQueue<'a> {
256
275
let msg = "The following warnings were emitted during compilation:" ;
257
276
self . emit_warnings ( Some ( msg) , & key, cx) ?;
258
277
259
- if self . active > 0 {
278
+ if ! self . active . is_empty ( ) {
260
279
error = Some ( format_err ! ( "build failed" ) ) ;
261
280
handle_error ( e, & mut * cx. bcx . config . shell ( ) ) ;
262
281
cx. bcx . config . shell ( ) . warn (
@@ -274,6 +293,7 @@ impl<'a> JobQueue<'a> {
274
293
}
275
294
}
276
295
}
296
+ drop ( progress) ;
277
297
278
298
let build_type = if self . is_release { "release" } else { "dev" } ;
279
299
// NOTE: This may be a bit inaccurate, since this may not display the
@@ -334,7 +354,7 @@ impl<'a> JobQueue<'a> {
334
354
) -> CargoResult < ( ) > {
335
355
info ! ( "start: {:?}" , key) ;
336
356
337
- self . active += 1 ;
357
+ self . active . push ( key ) ;
338
358
* self . counts . get_mut ( key. pkg ) . unwrap ( ) -= 1 ;
339
359
340
360
let my_tx = self . tx . clone ( ) ;
0 commit comments