@@ -529,11 +529,44 @@ pub struct MatrixOptions {
529529 pub no_prune_implied : bool ,
530530}
531531
532+ fn load_configs_for_packages ( packages : & [ & cargo_metadata:: Package ] ) -> eyre:: Result < Vec < Config > > {
533+ packages
534+ . iter ( )
535+ . map ( |package| package. config ( ) )
536+ . collect :: < eyre:: Result < Vec < _ > > > ( )
537+ }
538+
539+ fn single_target_plans < ' a > (
540+ packages : & [ & ' a cargo_metadata:: Package ] ,
541+ configs : & ' a [ Config ] ,
542+ target : & TargetTriple ,
543+ ) -> TargetPlans < ' a > {
544+ let effective_target = EffectiveTarget {
545+ triple : target. clone ( ) ,
546+ source : TargetSource :: Cli ,
547+ } ;
548+
549+ TargetPlans {
550+ plans : vec ! [ TargetPlan {
551+ target: target. clone( ) ,
552+ packages: packages
553+ . iter( )
554+ . zip( configs)
555+ . map( |( package, config) | PlannedPackage {
556+ package,
557+ config,
558+ target: effective_target. clone( ) ,
559+ } )
560+ . collect( ) ,
561+ } ] ,
562+ contains_configured_assignments : false ,
563+ }
564+ }
565+
532566/// Print a JSON feature matrix for the given packages to stdout.
533567///
534- /// The matrix is a JSON array of objects produced from each package's
535- /// configuration and the feature combinations returned by
536- /// [`Package::feature_matrix`].
568+ /// The matrix is a JSON array of objects produced from each package's resolved
569+ /// target-specific configuration and feature combinations.
537570///
538571/// # Errors
539572///
@@ -545,56 +578,19 @@ pub fn print_feature_matrix_for_target(
545578 evaluator : & mut impl crate :: cfg_eval:: CfgEvaluator ,
546579 options : & MatrixOptions ,
547580) -> eyre:: Result < ExitCode > {
548- let per_package_features = packages
549- . iter ( )
550- . map ( |pkg| {
551- let base_config = pkg. config ( ) ?;
552- let config = crate :: config:: resolve:: resolve_config ( & base_config, target, evaluator) ?;
553- let features = if options. packages_only {
554- vec ! [ "default" . to_string( ) ]
555- } else {
556- let combos = pkg. feature_combinations ( & config) ?;
557- let combos = crate :: implication:: maybe_prune (
558- combos,
559- & pkg. features ,
560- & config,
561- options. no_prune_implied ,
562- ) ;
563- combos
564- . keep
565- . into_iter ( )
566- . map ( |combo| combo. into_iter ( ) . join ( "," ) )
567- . collect ( )
568- } ;
569- Ok :: < _ , eyre:: Report > ( ( pkg. name . clone ( ) , config, features) )
570- } )
571- . collect :: < Result < Vec < _ > , _ > > ( ) ?;
572-
573- let matrix: Vec < serde_json:: Value > = per_package_features
574- . into_iter ( )
575- . flat_map ( |( name, config, features) | {
576- let target = target. as_str ( ) . to_string ( ) ;
577- features. into_iter ( ) . map ( move |ft| {
578- use serde_json_merge:: { iter:: dfs:: Dfs , merge:: Merge } ;
579-
580- let mut out = serde_json:: json!( config. matrix) ;
581- out. merge :: < Dfs > ( & serde_json:: json!( {
582- "name" : name,
583- "target" : target,
584- "features" : ft,
585- } ) ) ;
586- out
587- } )
588- } )
589- . collect ( ) ;
590-
591- let matrix = if options. pretty {
592- serde_json:: to_string_pretty ( & matrix)
593- } else {
594- serde_json:: to_string ( & matrix)
595- } ?;
596- println ! ( "{matrix}" ) ;
597- Ok ( None )
581+ let configs = load_configs_for_packages ( packages) ?;
582+ let target_plans = single_target_plans ( packages, & configs, target) ;
583+ let build_options = Options {
584+ no_prune_implied : options. no_prune_implied ,
585+ ..Options :: default ( )
586+ } ;
587+ let plan_set = build_execution_plans (
588+ & target_plans,
589+ & build_options,
590+ options. packages_only ,
591+ evaluator,
592+ ) ?;
593+ print_matrix_for_execution_plans ( & plan_set, options)
598594}
599595
600596/// A resolved, owned execution plan for one concrete target.
@@ -1023,30 +1019,8 @@ pub fn run_cargo_command_for_target(
10231019 target : & TargetTriple ,
10241020 evaluator : & mut impl CfgEvaluator ,
10251021) -> eyre:: Result < ExitCode > {
1026- let configs: Vec < Config > = packages
1027- . iter ( )
1028- . map ( |package| package. config ( ) )
1029- . collect :: < eyre:: Result < Vec < _ > > > ( ) ?;
1030-
1031- let target_plans = TargetPlans {
1032- plans : vec ! [ TargetPlan {
1033- target: target. clone( ) ,
1034- packages: packages
1035- . iter( )
1036- . zip( & configs)
1037- . map( |( package, config) | PlannedPackage {
1038- package,
1039- config,
1040- target: EffectiveTarget {
1041- triple: target. clone( ) ,
1042- source: TargetSource :: Cli ,
1043- } ,
1044- } )
1045- . collect( ) ,
1046- } ] ,
1047- contains_configured_assignments : false ,
1048- } ;
1049-
1022+ let configs = load_configs_for_packages ( packages) ?;
1023+ let target_plans = single_target_plans ( packages, & configs, target) ;
10501024 let plan_set = build_execution_plans ( & target_plans, options, false , evaluator) ?;
10511025 run_execution_plans (
10521026 & plan_set,
@@ -1198,18 +1172,14 @@ fn execute_serial(
11981172 seen_diagnostics,
11991173 stdout,
12001174 ) ?;
1201- let should_stop = ctx. options . fail_fast && !result. summary . pedantic_success ;
1202- let exit_code = result. summary . exit_code ;
1203- summary. push ( result. summary ) ;
1204- if should_stop {
1205- if ctx. options . summary_only {
1206- io:: copy ( & mut io:: Cursor :: new ( result. colored_output ) , stdout) ?;
1207- stdout. flush ( ) . ok ( ) ;
1208- }
1209- let code =
1210- print_summary ( & summary, plan_set. show_pruned , stdout, start. elapsed ( ) )
1211- . or ( exit_code)
1212- . unwrap_or ( 1 ) ;
1175+ if let Some ( code) = record_result_and_maybe_stop (
1176+ & mut summary,
1177+ result,
1178+ plan_set. show_pruned ,
1179+ ctx,
1180+ stdout,
1181+ start,
1182+ ) ? {
12131183 return Ok ( Some ( code) ) ;
12141184 }
12151185 }
@@ -1277,17 +1247,14 @@ fn execute_aggregate(
12771247 seen_diagnostics,
12781248 stdout,
12791249 ) ?;
1280- let should_stop = ctx. options . fail_fast && !result. summary . pedantic_success ;
1281- let exit_code = result. summary . exit_code ;
1282- summary. push ( result. summary ) ;
1283- if should_stop {
1284- if ctx. options . summary_only {
1285- io:: copy ( & mut io:: Cursor :: new ( result. colored_output ) , stdout) ?;
1286- stdout. flush ( ) . ok ( ) ;
1287- }
1288- let code = print_summary ( & summary, plan_set. show_pruned , stdout, start. elapsed ( ) )
1289- . or ( exit_code)
1290- . unwrap_or ( 1 ) ;
1250+ if let Some ( code) = record_result_and_maybe_stop (
1251+ & mut summary,
1252+ result,
1253+ plan_set. show_pruned ,
1254+ ctx,
1255+ stdout,
1256+ start,
1257+ ) ? {
12911258 return Ok ( Some ( code) ) ;
12921259 }
12931260 }
@@ -1300,6 +1267,37 @@ fn execute_aggregate(
13001267 ) )
13011268}
13021269
1270+ fn record_result_and_maybe_stop (
1271+ summary : & mut Vec < Summary > ,
1272+ result : CombinationResult ,
1273+ show_pruned : bool ,
1274+ ctx : & RunContext < ' _ > ,
1275+ stdout : & mut StandardStream ,
1276+ start : Instant ,
1277+ ) -> eyre:: Result < ExitCode > {
1278+ let CombinationResult {
1279+ summary : result_summary,
1280+ colored_output,
1281+ } = result;
1282+ let should_stop = ctx. options . fail_fast && !result_summary. pedantic_success ;
1283+ let exit_code = result_summary. exit_code ;
1284+ summary. push ( result_summary) ;
1285+
1286+ if !should_stop {
1287+ return Ok ( None ) ;
1288+ }
1289+
1290+ if ctx. options . summary_only {
1291+ io:: copy ( & mut io:: Cursor :: new ( colored_output) , stdout) ?;
1292+ stdout. flush ( ) . ok ( ) ;
1293+ }
1294+ Ok ( Some (
1295+ print_summary ( summary, show_pruned, stdout, start. elapsed ( ) )
1296+ . or ( exit_code)
1297+ . unwrap_or ( 1 ) ,
1298+ ) )
1299+ }
1300+
13031301/// Transpose per-target execution plans into aggregate-mode invocations.
13041302///
13051303/// The resulting order is package first-appearance order, sorted canonical combo
0 commit comments