@@ -17,6 +17,7 @@ use crate::util::{closest_msg, CargoResult};
17
17
18
18
use super :: compile_filter:: { CompileFilter , FilterRule , LibRule } ;
19
19
use super :: packages:: build_glob;
20
+ use super :: Packages ;
20
21
21
22
/// A proposed target.
22
23
///
@@ -267,14 +268,37 @@ impl<'a> UnitGenerator<'a, '_> {
267
268
} )
268
269
. collect :: < Vec < _ > > ( ) ;
269
270
let suggestion = closest_msg ( target_name, targets. iter ( ) , |t| t. name ( ) , "target" ) ;
271
+ let targets_elsewhere = self . get_targets_from_other_packages ( filter) ?;
272
+ let need_append_targets_elsewhere = !targets_elsewhere. is_empty ( ) ;
273
+ let append_targets_elsewhere = |msg : & mut String , prefix : & str | {
274
+ let mut available_msg = Vec :: new ( ) ;
275
+ for ( package, targets) in targets_elsewhere {
276
+ if !targets. is_empty ( ) {
277
+ available_msg. push ( format ! (
278
+ "help: Available {target_desc} in `{package}` package:"
279
+ ) ) ;
280
+ for target in targets {
281
+ available_msg. push ( format ! ( " {target}" ) ) ;
282
+ }
283
+ }
284
+ }
285
+ if !available_msg. is_empty ( ) {
286
+ write ! ( msg, "{prefix}{}" , available_msg. join( "\n " ) ) ?;
287
+ }
288
+ CargoResult :: Ok ( ( ) )
289
+ } ;
270
290
if !suggestion. is_empty ( ) {
271
- anyhow:: bail!(
291
+ let mut msg = String :: new ( ) ;
292
+ write ! (
293
+ msg,
272
294
"no {} target {} `{}`{}" ,
273
295
target_desc,
274
296
if is_glob { "matches pattern" } else { "named" } ,
275
297
target_name,
276
- suggestion
277
- ) ;
298
+ suggestion,
299
+ ) ?;
300
+ append_targets_elsewhere ( & mut msg, "\n " ) ?;
301
+ anyhow:: bail!( msg) ;
278
302
} else {
279
303
let mut msg = String :: new ( ) ;
280
304
writeln ! (
@@ -284,7 +308,9 @@ impl<'a> UnitGenerator<'a, '_> {
284
308
if is_glob { "matches pattern" } else { "named" } ,
285
309
target_name,
286
310
) ?;
287
- if !targets. is_empty ( ) {
311
+
312
+ append_targets_elsewhere ( & mut msg, "" ) ?;
313
+ if !targets. is_empty ( ) && !need_append_targets_elsewhere {
288
314
writeln ! ( msg, "Available {} targets:" , target_desc) ?;
289
315
for target in targets {
290
316
writeln ! ( msg, " {}" , target. name( ) ) ?;
@@ -296,6 +322,32 @@ impl<'a> UnitGenerator<'a, '_> {
296
322
Ok ( proposals)
297
323
}
298
324
325
+ fn get_targets_from_other_packages (
326
+ & self ,
327
+ filter_fn : impl Fn ( & Target ) -> bool ,
328
+ ) -> CargoResult < Vec < ( & str , Vec < & str > ) > > {
329
+ let packages = Packages :: All ( Vec :: new ( ) ) . get_packages ( self . ws ) ?;
330
+ let targets = packages
331
+ . into_iter ( )
332
+ . filter_map ( |pkg| {
333
+ let mut targets: Vec < _ > = pkg
334
+ . manifest ( )
335
+ . targets ( )
336
+ . iter ( )
337
+ . filter_map ( |target| filter_fn ( target) . then ( || target. name ( ) ) )
338
+ . collect ( ) ;
339
+ if targets. is_empty ( ) {
340
+ None
341
+ } else {
342
+ targets. sort ( ) ;
343
+ Some ( ( pkg. name ( ) . as_str ( ) , targets) )
344
+ }
345
+ } )
346
+ . collect ( ) ;
347
+
348
+ Ok ( targets)
349
+ }
350
+
299
351
/// Returns a list of proposed targets based on command-line target selection flags.
300
352
fn list_rule_targets (
301
353
& self ,
0 commit comments