@@ -92,8 +92,8 @@ impl Default for CargoFeatures {
92
92
pub struct CargoConfig {
93
93
/// List of features to activate.
94
94
pub features : CargoFeatures ,
95
- /// rustc target
96
- pub target : Option < String > ,
95
+ /// rustc targets
96
+ pub targets : Vec < String > ,
97
97
/// Don't load sysroot crates (`std`, `core` & friends). Might be useful
98
98
/// when debugging isolated issues.
99
99
pub no_sysroot : bool ,
@@ -269,11 +269,7 @@ impl CargoWorkspace {
269
269
config : & CargoConfig ,
270
270
progress : & dyn Fn ( String ) ,
271
271
) -> Result < cargo_metadata:: Metadata > {
272
- let target = config
273
- . target
274
- . clone ( )
275
- . or_else ( || cargo_config_build_target ( cargo_toml, & config. extra_env ) )
276
- . or_else ( || rustc_discover_host_triple ( cargo_toml, & config. extra_env ) ) ;
272
+ let targets = find_list_of_build_targets ( config, cargo_toml) ;
277
273
278
274
let mut meta = MetadataCommand :: new ( ) ;
279
275
meta. cargo_path ( toolchain:: cargo ( ) ) ;
@@ -295,8 +291,12 @@ impl CargoWorkspace {
295
291
}
296
292
meta. current_dir ( current_dir. as_os_str ( ) ) ;
297
293
298
- if let Some ( target) = target {
299
- meta. other_options ( vec ! [ String :: from( "--filter-platform" ) , target] ) ;
294
+ if !targets. is_empty ( ) {
295
+ let other_options: Vec < _ > = targets
296
+ . into_iter ( )
297
+ . flat_map ( |target| [ "--filter-platform" . to_string ( ) , target] )
298
+ . collect ( ) ;
299
+ meta. other_options ( other_options) ;
300
300
}
301
301
302
302
// FIXME: Fetching metadata is a slow process, as it might require
@@ -466,10 +466,23 @@ impl CargoWorkspace {
466
466
}
467
467
}
468
468
469
+ fn find_list_of_build_targets ( config : & CargoConfig , cargo_toml : & ManifestPath ) -> Vec < String > {
470
+ if !config. targets . is_empty ( ) {
471
+ return config. targets . clone ( ) ;
472
+ }
473
+
474
+ let build_targets = cargo_config_build_target ( cargo_toml, & config. extra_env ) ;
475
+ if !build_targets. is_empty ( ) {
476
+ return build_targets;
477
+ }
478
+
479
+ rustc_discover_host_triple ( cargo_toml, & config. extra_env )
480
+ }
481
+
469
482
fn rustc_discover_host_triple (
470
483
cargo_toml : & ManifestPath ,
471
484
extra_env : & FxHashMap < String , String > ,
472
- ) -> Option < String > {
485
+ ) -> Vec < String > {
473
486
let mut rustc = Command :: new ( toolchain:: rustc ( ) ) ;
474
487
rustc. envs ( extra_env) ;
475
488
rustc. current_dir ( cargo_toml. parent ( ) ) . arg ( "-vV" ) ;
@@ -479,37 +492,46 @@ fn rustc_discover_host_triple(
479
492
let field = "host: " ;
480
493
let target = stdout. lines ( ) . find_map ( |l| l. strip_prefix ( field) ) ;
481
494
if let Some ( target) = target {
482
- Some ( target. to_string ( ) )
495
+ [ target. to_string ( ) ] . to_vec ( )
483
496
} else {
484
497
// If we fail to resolve the host platform, it's not the end of the world.
485
498
tracing:: info!( "rustc -vV did not report host platform, got:\n {}" , stdout) ;
486
- None
499
+ Vec :: new ( )
487
500
}
488
501
}
489
502
Err ( e) => {
490
503
tracing:: warn!( "Failed to discover host platform: {}" , e) ;
491
- None
504
+ Vec :: new ( )
492
505
}
493
506
}
494
507
}
495
508
496
509
fn cargo_config_build_target (
497
510
cargo_toml : & ManifestPath ,
498
511
extra_env : & FxHashMap < String , String > ,
499
- ) -> Option < String > {
512
+ ) -> Vec < String > {
500
513
let mut cargo_config = Command :: new ( toolchain:: cargo ( ) ) ;
501
514
cargo_config. envs ( extra_env) ;
502
515
cargo_config
503
516
. current_dir ( cargo_toml. parent ( ) )
504
517
. args ( & [ "-Z" , "unstable-options" , "config" , "get" , "build.target" ] )
505
518
. env ( "RUSTC_BOOTSTRAP" , "1" ) ;
506
519
// if successful we receive `build.target = "target-triple"`
520
+ // or `build.target = ["<target 1>", ..]`
507
521
tracing:: debug!( "Discovering cargo config target by {:?}" , cargo_config) ;
508
- match utf8_stdout ( cargo_config) {
509
- Ok ( stdout) => stdout
510
- . strip_prefix ( "build.target = \" " )
511
- . and_then ( |stdout| stdout. strip_suffix ( '"' ) )
512
- . map ( ToOwned :: to_owned) ,
513
- Err ( _) => None ,
522
+ utf8_stdout ( cargo_config) . map ( parse_output_cargo_config_build_target) . unwrap_or_default ( )
523
+ }
524
+
525
+ fn parse_output_cargo_config_build_target ( stdout : String ) -> Vec < String > {
526
+ let trimmed = stdout. trim_start_matches ( "build.target = " ) . trim_matches ( '"' ) ;
527
+
528
+ if !trimmed. starts_with ( '[' ) {
529
+ return [ trimmed. to_string ( ) ] . to_vec ( ) ;
530
+ }
531
+
532
+ let res = serde_json:: from_str ( trimmed) ;
533
+ if let Err ( e) = & res {
534
+ tracing:: warn!( "Failed to parse `build.target` as an array of target: {}`" , e) ;
514
535
}
536
+ res. unwrap_or_default ( )
515
537
}
0 commit comments