1
- use std:: collections:: { HashMap , HashSet } ;
2
1
use std:: cell:: Cell ;
2
+ use std:: collections:: { HashMap , HashSet } ;
3
3
use std:: io;
4
4
use std:: marker;
5
5
use std:: sync:: mpsc:: { channel, Receiver , Sender } ;
@@ -152,7 +152,7 @@ impl<'a, 'cfg> JobQueue<'a, 'cfg> {
152
152
job : Job ,
153
153
) -> CargoResult < ( ) > {
154
154
let dependencies = cx. dep_targets ( unit) ;
155
- let dependencies = dependencies
155
+ let mut queue_deps = dependencies
156
156
. iter ( )
157
157
. filter ( |unit| {
158
158
// Binaries aren't actually needed to *compile* tests, just to run
@@ -171,10 +171,52 @@ impl<'a, 'cfg> JobQueue<'a, 'cfg> {
171
171
Artifact :: All
172
172
} ;
173
173
( dep, artifact)
174
- } ) ;
175
- self . queue . queue ( * unit, job, dependencies) ;
174
+ } )
175
+ . collect :: < Vec < _ > > ( ) ;
176
+
177
+ // This is somewhat tricky, but we may need to synthesize some
178
+ // dependencies for this target if it requires full upstream
179
+ // compilations to have completed. If we're in pipelining mode then some
180
+ // dependency edges may be `Metadata` due to the above clause (as
181
+ // opposed to everything being `All`). For example consider:
182
+ //
183
+ // a (binary)
184
+ // └ b (lib)
185
+ // └ c (lib)
186
+ //
187
+ // Here the dependency edge from B to C will be `Metadata`, and the
188
+ // dependency edge from A to B will be `All`. For A to be compiled,
189
+ // however, it currently actually needs the full rlib of C. This means
190
+ // that we need to synthesize a dependency edge for the dependency graph
191
+ // from A to C. That's done here.
192
+ //
193
+ // This will walk all dependencies of the current target, and if any of
194
+ // *their* dependencies are `Metadata` then we depend on the `All` of
195
+ // the target as well. This should ensure that edges changed to
196
+ // `Metadata` propagate upwards `All` dependencies to anything that
197
+ // transitively contains the `Metadata` edge.
198
+ if unit. target . requires_upstream_objects ( ) {
199
+ for dep in dependencies. iter ( ) {
200
+ depend_on_deps_of_deps ( cx, & mut queue_deps, dep) ;
201
+ }
202
+
203
+ fn depend_on_deps_of_deps < ' a > (
204
+ cx : & Context < ' a , ' _ > ,
205
+ deps : & mut Vec < ( Unit < ' a > , Artifact ) > ,
206
+ unit : & Unit < ' a > ,
207
+ ) {
208
+ for dep in cx. dep_targets ( unit) {
209
+ if cx. only_requires_rmeta ( unit, & dep) {
210
+ deps. push ( ( dep, Artifact :: All ) ) ;
211
+ depend_on_deps_of_deps ( cx, deps, & dep) ;
212
+ }
213
+ }
214
+ }
215
+ }
216
+
217
+ self . queue . queue ( * unit, job, queue_deps) ;
176
218
* self . counts . entry ( unit. pkg . package_id ( ) ) . or_insert ( 0 ) += 1 ;
177
- Ok ( ( ) )
219
+ return Ok ( ( ) ) ;
178
220
}
179
221
180
222
/// Executes all jobs necessary to build the dependency graph.
@@ -430,7 +472,6 @@ impl<'a, 'cfg> JobQueue<'a, 'cfg> {
430
472
cx : & Context < ' a , ' _ > ,
431
473
scope : & Scope < ' a > ,
432
474
) -> CargoResult < ( ) > {
433
-
434
475
let id = self . next_id ;
435
476
self . next_id = id. checked_add ( 1 ) . unwrap ( ) ;
436
477
@@ -464,7 +505,9 @@ impl<'a, 'cfg> JobQueue<'a, 'cfg> {
464
505
// we need to make sure that the metadata is flagged as produced so
465
506
// send a synthetic message here.
466
507
if state. rmeta_required . get ( ) && res. is_ok ( ) {
467
- my_tx. send ( Message :: Finish ( id, Artifact :: Metadata , Ok ( ( ) ) ) ) . unwrap ( ) ;
508
+ my_tx
509
+ . send ( Message :: Finish ( id, Artifact :: Metadata , Ok ( ( ) ) ) )
510
+ . unwrap ( ) ;
468
511
}
469
512
470
513
my_tx. send ( Message :: Finish ( id, Artifact :: All , res) ) . unwrap ( ) ;
@@ -513,7 +556,12 @@ impl<'a, 'cfg> JobQueue<'a, 'cfg> {
513
556
Ok ( ( ) )
514
557
}
515
558
516
- fn finish ( & mut self , unit : & Unit < ' a > , artifact : Artifact , cx : & mut Context < ' _ , ' _ > ) -> CargoResult < ( ) > {
559
+ fn finish (
560
+ & mut self ,
561
+ unit : & Unit < ' a > ,
562
+ artifact : Artifact ,
563
+ cx : & mut Context < ' _ , ' _ > ,
564
+ ) -> CargoResult < ( ) > {
517
565
if unit. mode . is_run_custom_build ( ) && cx. bcx . show_warnings ( unit. pkg . package_id ( ) ) {
518
566
self . emit_warnings ( None , unit, cx) ?;
519
567
}
0 commit comments