From 18522122f1238d7200a9c4bcc696e707385bcbb1 Mon Sep 17 00:00:00 2001 From: datdenkikniet Date: Sat, 15 Apr 2023 00:26:16 +0200 Subject: xtask: forward globals through the chain and add stderr-inheritance flag --- xtask/src/cargo_commands.rs | 39 ++++++++++++++++++++++++++++----------- 1 file changed, 28 insertions(+), 11 deletions(-) (limited to 'xtask/src/cargo_commands.rs') diff --git a/xtask/src/cargo_commands.rs b/xtask/src/cargo_commands.rs index 7ac7aea..90a8037 100644 --- a/xtask/src/cargo_commands.rs +++ b/xtask/src/cargo_commands.rs @@ -1,5 +1,7 @@ use crate::{ - argument_parsing::{Backends, BuildOrCheck, ExtraArguments, Package, PackageOpt, TestMetadata}, + argument_parsing::{ + Backends, BuildOrCheck, ExtraArguments, Globals, Package, PackageOpt, TestMetadata, + }, command::{BuildMode, CargoCommand}, command_parser, package_feature_extractor, DEFAULT_FEATURES, }; @@ -8,6 +10,7 @@ use rayon::prelude::*; /// Cargo command to either build or check pub fn cargo( + globals: &Globals, operation: BuildOrCheck, cargoarg: &Option<&str>, package: &PackageOpt, @@ -31,7 +34,7 @@ pub fn cargo( mode: BuildMode::Release, }, }; - command_parser(&command, false)?; + command_parser(globals, &command, false)?; Ok(()) } @@ -39,6 +42,7 @@ pub fn cargo( /// /// The examples are in rtic/examples pub fn cargo_example( + globals: &Globals, operation: BuildOrCheck, cargoarg: &Option<&str>, backend: Backends, @@ -68,7 +72,7 @@ pub fn cargo_example( }, }; - if let Err(err) = command_parser(&command, false) { + if let Err(err) = command_parser(globals, &command, false) { error!("{err}"); } }); @@ -78,12 +82,14 @@ pub fn cargo_example( /// Run cargo clippy on selected package pub fn cargo_clippy( + globals: &Globals, cargoarg: &Option<&str>, package: &PackageOpt, backend: Backends, ) -> anyhow::Result<()> { let features = package_feature_extractor(package, backend); command_parser( + globals, &CargoCommand::Clippy { cargoarg, package: package.package, @@ -97,11 +103,13 @@ pub fn cargo_clippy( /// Run cargo fmt on selected package pub fn cargo_format( + globals: &Globals, cargoarg: &Option<&str>, package: &PackageOpt, check_only: bool, ) -> anyhow::Result<()> { command_parser( + globals, &CargoCommand::Format { cargoarg, package: package.package, @@ -114,6 +122,7 @@ pub fn cargo_format( /// Run cargo doc pub fn cargo_doc( + globals: &Globals, cargoarg: &Option<&str>, backend: Backends, arguments: &Option, @@ -125,6 +134,7 @@ pub fn cargo_doc( )); command_parser( + globals, &CargoCommand::Doc { cargoarg, features, @@ -138,10 +148,14 @@ pub fn cargo_doc( /// Run cargo test on the selcted package or all packages /// /// If no package is specified, loop through all packages -pub fn cargo_test(package: &PackageOpt, backend: Backends) -> anyhow::Result<()> { +pub fn cargo_test( + globals: &Globals, + package: &PackageOpt, + backend: Backends, +) -> anyhow::Result<()> { if let Some(package) = package.package { let cmd = TestMetadata::match_package(package, backend); - command_parser(&cmd, false)?; + command_parser(globals, &cmd, false)?; } else { // Iterate over all workspace packages for package in [ @@ -154,7 +168,7 @@ pub fn cargo_test(package: &PackageOpt, backend: Backends) -> anyhow::Result<()> ] { let mut error_messages = vec![]; let cmd = &TestMetadata::match_package(package, backend); - if let Err(err) = command_parser(cmd, false) { + if let Err(err) = command_parser(globals, cmd, false) { error_messages.push(err); } @@ -169,8 +183,9 @@ pub fn cargo_test(package: &PackageOpt, backend: Backends) -> anyhow::Result<()> } /// Use mdbook to build the book -pub fn cargo_book(arguments: &Option) -> anyhow::Result<()> { +pub fn cargo_book(globals: &Globals, arguments: &Option) -> anyhow::Result<()> { command_parser( + globals, &CargoCommand::Book { arguments: arguments.clone(), }, @@ -183,6 +198,7 @@ pub fn cargo_book(arguments: &Option) -> anyhow::Result<()> { /// /// Supports updating the expected output via the overwrite argument pub fn run_test( + globals: &Globals, cargoarg: &Option<&str>, backend: Backends, examples: &[String], @@ -200,7 +216,7 @@ pub fn run_test( )), mode: BuildMode::Release, }; - if let Err(err) = command_parser(&cmd, false) { + if let Err(err) = command_parser(globals, &cmd, false) { error!("{err}"); } @@ -216,7 +232,7 @@ pub fn run_test( mode: BuildMode::Release, }; - if let Err(err) = command_parser(&cmd, overwrite) { + if let Err(err) = command_parser(globals, &cmd, overwrite) { error!("{err}"); } }); @@ -226,6 +242,7 @@ pub fn run_test( /// Check the binary sizes of examples pub fn build_and_check_size( + globals: &Globals, cargoarg: &Option<&str>, backend: Backends, examples: &[String], @@ -244,7 +261,7 @@ pub fn build_and_check_size( )), mode: BuildMode::Release, }; - if let Err(err) = command_parser(&cmd, false) { + if let Err(err) = command_parser(globals, &cmd, false) { error!("{err}"); } @@ -260,7 +277,7 @@ pub fn build_and_check_size( mode: BuildMode::Release, arguments: arguments.clone(), }; - if let Err(err) = command_parser(&cmd, false) { + if let Err(err) = command_parser(globals, &cmd, false) { error!("{err}"); } }); -- cgit v1.2.3 From 4adae80f2d575b631b0bc1aef4b7272e62acedb6 Mon Sep 17 00:00:00 2001 From: datdenkikniet Date: Sat, 15 Apr 2023 00:50:46 +0200 Subject: xtask: don't add default arguments if building for a no_std target --- xtask/src/cargo_commands.rs | 64 +++++++++++++++++---------------------------- 1 file changed, 24 insertions(+), 40 deletions(-) (limited to 'xtask/src/cargo_commands.rs') diff --git a/xtask/src/cargo_commands.rs b/xtask/src/cargo_commands.rs index 90a8037..af61141 100644 --- a/xtask/src/cargo_commands.rs +++ b/xtask/src/cargo_commands.rs @@ -3,7 +3,7 @@ use crate::{ Backends, BuildOrCheck, ExtraArguments, Globals, Package, PackageOpt, TestMetadata, }, command::{BuildMode, CargoCommand}, - command_parser, package_feature_extractor, DEFAULT_FEATURES, + command_parser, package_feature_extractor, }; use log::error; use rayon::prelude::*; @@ -16,20 +16,21 @@ pub fn cargo( package: &PackageOpt, backend: Backends, ) -> anyhow::Result<()> { - let features = package_feature_extractor(package, backend); + let target = backend.to_target(); + let features = package_feature_extractor(target, package, backend); let command = match operation { BuildOrCheck::Check => CargoCommand::Check { cargoarg, package: package.package, - target: backend.to_target(), + target, features, mode: BuildMode::Release, }, BuildOrCheck::Build => CargoCommand::Build { cargoarg, package: package.package, - target: backend.to_target(), + target, features, mode: BuildMode::Release, }, @@ -49,11 +50,7 @@ pub fn cargo_example( examples: &[String], ) -> anyhow::Result<()> { examples.into_par_iter().for_each(|example| { - let features = Some(format!( - "{},{}", - DEFAULT_FEATURES, - backend.to_rtic_feature() - )); + let features = Some(backend.to_target().and_features(backend.to_rtic_feature())); let command = match operation { BuildOrCheck::Check => CargoCommand::ExampleCheck { @@ -87,13 +84,14 @@ pub fn cargo_clippy( package: &PackageOpt, backend: Backends, ) -> anyhow::Result<()> { - let features = package_feature_extractor(package, backend); + let target = backend.to_target(); + let features = package_feature_extractor(target, package, backend); command_parser( globals, &CargoCommand::Clippy { cargoarg, package: package.package, - target: backend.to_target(), + target, features, }, false, @@ -127,11 +125,7 @@ pub fn cargo_doc( backend: Backends, arguments: &Option, ) -> anyhow::Result<()> { - let features = Some(format!( - "{},{}", - DEFAULT_FEATURES, - backend.to_rtic_feature() - )); + let features = Some(backend.to_target().and_features(backend.to_rtic_feature())); command_parser( globals, @@ -145,7 +139,7 @@ pub fn cargo_doc( Ok(()) } -/// Run cargo test on the selcted package or all packages +/// Run cargo test on the selected package or all packages /// /// If no package is specified, loop through all packages pub fn cargo_test( @@ -204,16 +198,15 @@ pub fn run_test( examples: &[String], overwrite: bool, ) -> anyhow::Result<()> { + let target = backend.to_target(); + let features = Some(target.and_features(backend.to_rtic_feature())); + examples.into_par_iter().for_each(|example| { let cmd = CargoCommand::ExampleBuild { cargoarg: &Some("--quiet"), example, - target: backend.to_target(), - features: Some(format!( - "{},{}", - DEFAULT_FEATURES, - backend.to_rtic_feature() - )), + target, + features: features.clone(), mode: BuildMode::Release, }; if let Err(err) = command_parser(globals, &cmd, false) { @@ -223,12 +216,8 @@ pub fn run_test( let cmd = CargoCommand::Qemu { cargoarg, example, - target: backend.to_target(), - features: Some(format!( - "{},{}", - DEFAULT_FEATURES, - backend.to_rtic_feature() - )), + target, + features: features.clone(), mode: BuildMode::Release, }; @@ -248,17 +237,16 @@ pub fn build_and_check_size( examples: &[String], arguments: &Option, ) -> anyhow::Result<()> { + let target = backend.to_target(); + let features = Some(target.and_features(backend.to_rtic_feature())); + examples.into_par_iter().for_each(|example| { // Make sure the requested example(s) are built let cmd = CargoCommand::ExampleBuild { cargoarg: &Some("--quiet"), example, - target: backend.to_target(), - features: Some(format!( - "{},{}", - DEFAULT_FEATURES, - backend.to_rtic_feature() - )), + target, + features: features.clone(), mode: BuildMode::Release, }; if let Err(err) = command_parser(globals, &cmd, false) { @@ -269,11 +257,7 @@ pub fn build_and_check_size( cargoarg, example, target: backend.to_target(), - features: Some(format!( - "{},{}", - DEFAULT_FEATURES, - backend.to_rtic_feature() - )), + features: features.clone(), mode: BuildMode::Release, arguments: arguments.clone(), }; -- cgit v1.2.3 From 480aa210594a1ea808da93614aa49a508f9f35af Mon Sep 17 00:00:00 2001 From: datdenkikniet Date: Sat, 15 Apr 2023 10:03:52 +0200 Subject: Always run stuff for all packages if none is specified --- xtask/src/cargo_commands.rs | 149 ++++++++++++++++++++++++-------------------- 1 file changed, 80 insertions(+), 69 deletions(-) (limited to 'xtask/src/cargo_commands.rs') diff --git a/xtask/src/cargo_commands.rs b/xtask/src/cargo_commands.rs index af61141..2a15b3c 100644 --- a/xtask/src/cargo_commands.rs +++ b/xtask/src/cargo_commands.rs @@ -1,9 +1,7 @@ use crate::{ - argument_parsing::{ - Backends, BuildOrCheck, ExtraArguments, Globals, Package, PackageOpt, TestMetadata, - }, + argument_parsing::{Backends, BuildOrCheck, ExtraArguments, Globals, PackageOpt, TestMetadata}, command::{BuildMode, CargoCommand}, - command_parser, package_feature_extractor, + command_parser, }; use log::error; use rayon::prelude::*; @@ -16,26 +14,42 @@ pub fn cargo( package: &PackageOpt, backend: Backends, ) -> anyhow::Result<()> { - let target = backend.to_target(); - let features = package_feature_extractor(target, package, backend); + package.packages().for_each(|package| { + let target = backend.to_target(); + + let features = package.extract_features(target, backend); + + match operation { + BuildOrCheck::Check => { + log::debug!(target: "xtask::command", "Checking package: {package}") + } + BuildOrCheck::Build => { + log::debug!(target: "xtask::command", "Building package: {package}") + } + } + + let command = match operation { + BuildOrCheck::Check => CargoCommand::Check { + cargoarg, + package: Some(package), + target, + features, + mode: BuildMode::Release, + }, + BuildOrCheck::Build => CargoCommand::Build { + cargoarg, + package: Some(package), + target, + features, + mode: BuildMode::Release, + }, + }; + let res = command_parser(globals, &command, false); + if let Err(e) = res { + error!("{e}"); + } + }); - let command = match operation { - BuildOrCheck::Check => CargoCommand::Check { - cargoarg, - package: package.package, - target, - features, - mode: BuildMode::Release, - }, - BuildOrCheck::Build => CargoCommand::Build { - cargoarg, - package: package.package, - target, - features, - mode: BuildMode::Release, - }, - }; - command_parser(globals, &command, false)?; Ok(()) } @@ -84,18 +98,26 @@ pub fn cargo_clippy( package: &PackageOpt, backend: Backends, ) -> anyhow::Result<()> { - let target = backend.to_target(); - let features = package_feature_extractor(target, package, backend); - command_parser( - globals, - &CargoCommand::Clippy { - cargoarg, - package: package.package, - target, - features, - }, - false, - )?; + package.packages().for_each(|p| { + let target = backend.to_target(); + let features = p.extract_features(target, backend); + + let res = command_parser( + globals, + &CargoCommand::Clippy { + cargoarg, + package: Some(p), + target, + features, + }, + false, + ); + + if let Err(e) = res { + error!("{e}") + } + }); + Ok(()) } @@ -106,15 +128,22 @@ pub fn cargo_format( package: &PackageOpt, check_only: bool, ) -> anyhow::Result<()> { - command_parser( - globals, - &CargoCommand::Format { - cargoarg, - package: package.package, - check_only, - }, - false, - )?; + package.packages().for_each(|p| { + let res = command_parser( + globals, + &CargoCommand::Format { + cargoarg, + package: Some(p), + check_only, + }, + false, + ); + + if let Err(e) = res { + error!("{e}") + } + }); + Ok(()) } @@ -147,32 +176,13 @@ pub fn cargo_test( package: &PackageOpt, backend: Backends, ) -> anyhow::Result<()> { - if let Some(package) = package.package { - let cmd = TestMetadata::match_package(package, backend); - command_parser(globals, &cmd, false)?; - } else { - // Iterate over all workspace packages - for package in [ - Package::Rtic, - Package::RticCommon, - Package::RticMacros, - Package::RticMonotonics, - Package::RticSync, - Package::RticTime, - ] { - let mut error_messages = vec![]; - let cmd = &TestMetadata::match_package(package, backend); - if let Err(err) = command_parser(globals, cmd, false) { - error_messages.push(err); - } - - if !error_messages.is_empty() { - for err in error_messages { - error!("{err}"); - } - } + package.packages().for_each(|p| { + let cmd = &TestMetadata::match_package(p, backend); + if let Err(err) = command_parser(globals, cmd, false) { + error!("{err}") } - } + }); + Ok(()) } @@ -209,6 +219,7 @@ pub fn run_test( features: features.clone(), mode: BuildMode::Release, }; + if let Err(err) = command_parser(globals, &cmd, false) { error!("{err}"); } -- cgit v1.2.3 From 525703358bf52b74a01d9b0c04680d33621d60cd Mon Sep 17 00:00:00 2001 From: datdenkikniet Date: Sat, 15 Apr 2023 12:21:11 +0200 Subject: Rework command execution structure and make rayon optional (since it's not necessarily faster due to workspace wide lockfile contention) --- xtask/src/cargo_commands.rs | 261 +++++++++++++++++++++++++++++++------------- 1 file changed, 187 insertions(+), 74 deletions(-) (limited to 'xtask/src/cargo_commands.rs') diff --git a/xtask/src/cargo_commands.rs b/xtask/src/cargo_commands.rs index 2a15b3c..e88f31e 100644 --- a/xtask/src/cargo_commands.rs +++ b/xtask/src/cargo_commands.rs @@ -1,11 +1,145 @@ use crate::{ argument_parsing::{Backends, BuildOrCheck, ExtraArguments, Globals, PackageOpt, TestMetadata}, command::{BuildMode, CargoCommand}, - command_parser, + command_parser, RunResult, }; -use log::error; +use log::{error, info, Level}; + +#[cfg(feature = "rayon")] use rayon::prelude::*; +use iters::*; + +enum FinalRunResult<'c> { + Success(CargoCommand<'c>, RunResult), + Failed(CargoCommand<'c>, RunResult), + CommandError(anyhow::Error), +} + +fn run_and_convert<'a>( + (global, command, overwrite): (&Globals, CargoCommand<'a>, bool), +) -> FinalRunResult<'a> { + // Run the command + let result = command_parser(global, &command, overwrite); + match result { + // If running the command succeeded without looking at any of the results, + // log the data and see if the actual execution was succesfull too. + Ok(result) => { + if result.exit_status.success() { + FinalRunResult::Success(command, result) + } else { + FinalRunResult::Failed(command, result) + } + } + // If it didn't and some IO error occured, just panic + Err(e) => FinalRunResult::CommandError(e), + } +} + +fn handle_results(results: Vec) -> anyhow::Result<()> { + let errors = results.iter().filter_map(|r| { + if let FinalRunResult::Failed(c, r) = r { + Some((c, r)) + } else { + None + } + }); + + let successes = results.iter().filter_map(|r| { + if let FinalRunResult::Success(c, r) = r { + Some((c, r)) + } else { + None + } + }); + + let log_stdout_stderr = |level: Level| { + move |(command, result): (&CargoCommand, &RunResult)| { + let stdout = &result.stdout; + let stderr = &result.stderr; + if !stdout.is_empty() && !stderr.is_empty() { + log::log!( + level, + "Command output for {command}\nStdout:\n{stdout}\nStderr:\n{stderr}" + ); + } else if !stdout.is_empty() { + log::log!( + level, + "Command output for {command}\nStdout:\n{}", + stdout.trim_end() + ); + } else if !stderr.is_empty() { + log::log!( + level, + "Command output for {command}\nStderr:\n{}", + stderr.trim_end() + ); + } + } + }; + + successes.clone().for_each(log_stdout_stderr(Level::Debug)); + errors.clone().for_each(log_stdout_stderr(Level::Error)); + + successes.for_each(|(cmd, _)| { + info!("Succesfully executed {cmd}"); + }); + + errors.clone().for_each(|(cmd, _)| { + error!("Command {cmd} failed"); + }); + + if errors.count() != 0 { + Err(anyhow::anyhow!("Some commands failed.")) + } else { + Ok(()) + } +} + +pub trait CoalescingRunning { + /// Run all the commands in this iterator, and coalesce the results into + /// one error (if any individual commands failed) + fn run_and_coalesce(self) -> anyhow::Result<()>; +} + +#[cfg(not(feature = "rayon"))] +mod iters { + use super::*; + + pub fn examples_iter(examples: &[String]) -> impl Iterator { + examples.into_iter() + } + + impl<'g, 'c, I> CoalescingRunning for I + where + I: Iterator, bool)>, + { + fn run_and_coalesce(self) -> anyhow::Result<()> { + let results: Vec<_> = self.map(run_and_convert).collect(); + handle_results(results) + } + } +} + +#[cfg(feature = "rayon")] +mod iters { + use super::*; + + pub fn examples_iter(examples: &[String]) -> impl ParallelIterator { + examples.into_par_iter() + } + + impl<'g, 'c, I> CoalescingRunning for I + where + I: ParallelIterator, bool)>, + { + fn run_and_coalesce(self) -> anyhow::Result<()> { + let results: Vec<_> = self.map(run_and_convert).collect(); + handle_results(results) + } + } +} + /// Cargo command to either build or check pub fn cargo( globals: &Globals, @@ -14,7 +148,7 @@ pub fn cargo( package: &PackageOpt, backend: Backends, ) -> anyhow::Result<()> { - package.packages().for_each(|package| { + let runner = package.packages().map(|package| { let target = backend.to_target(); let features = package.extract_features(target, backend); @@ -44,13 +178,11 @@ pub fn cargo( mode: BuildMode::Release, }, }; - let res = command_parser(globals, &command, false); - if let Err(e) = res { - error!("{e}"); - } + + (globals, command, false) }); - Ok(()) + runner.run_and_coalesce() } /// Cargo command to either build or check all examples @@ -63,7 +195,7 @@ pub fn cargo_example( backend: Backends, examples: &[String], ) -> anyhow::Result<()> { - examples.into_par_iter().for_each(|example| { + let runner = examples_iter(examples).map(|example| { let features = Some(backend.to_target().and_features(backend.to_rtic_feature())); let command = match operation { @@ -82,13 +214,9 @@ pub fn cargo_example( mode: BuildMode::Release, }, }; - - if let Err(err) = command_parser(globals, &command, false) { - error!("{err}"); - } + (globals, command, false) }); - - Ok(()) + runner.run_and_coalesce() } /// Run cargo clippy on selected package @@ -98,27 +226,23 @@ pub fn cargo_clippy( package: &PackageOpt, backend: Backends, ) -> anyhow::Result<()> { - package.packages().for_each(|p| { + let runner = package.packages().map(|p| { let target = backend.to_target(); let features = p.extract_features(target, backend); - let res = command_parser( + ( globals, - &CargoCommand::Clippy { + CargoCommand::Clippy { cargoarg, package: Some(p), target, features, }, false, - ); - - if let Err(e) = res { - error!("{e}") - } + ) }); - Ok(()) + runner.run_and_coalesce() } /// Run cargo fmt on selected package @@ -128,23 +252,18 @@ pub fn cargo_format( package: &PackageOpt, check_only: bool, ) -> anyhow::Result<()> { - package.packages().for_each(|p| { - let res = command_parser( + let runner = package.packages().map(|p| { + ( globals, - &CargoCommand::Format { + CargoCommand::Format { cargoarg, package: Some(p), check_only, }, false, - ); - - if let Err(e) = res { - error!("{e}") - } + ) }); - - Ok(()) + runner.run_and_coalesce() } /// Run cargo doc @@ -176,26 +295,24 @@ pub fn cargo_test( package: &PackageOpt, backend: Backends, ) -> anyhow::Result<()> { - package.packages().for_each(|p| { - let cmd = &TestMetadata::match_package(p, backend); - if let Err(err) = command_parser(globals, cmd, false) { - error!("{err}") - } - }); - - Ok(()) + package + .packages() + .map(|p| (globals, TestMetadata::match_package(p, backend), false)) + .run_and_coalesce() } /// Use mdbook to build the book -pub fn cargo_book(globals: &Globals, arguments: &Option) -> anyhow::Result<()> { +pub fn cargo_book( + globals: &Globals, + arguments: &Option, +) -> anyhow::Result { command_parser( globals, &CargoCommand::Book { arguments: arguments.clone(), }, false, - )?; - Ok(()) + ) } /// Run examples @@ -211,33 +328,31 @@ pub fn run_test( let target = backend.to_target(); let features = Some(target.and_features(backend.to_rtic_feature())); - examples.into_par_iter().for_each(|example| { - let cmd = CargoCommand::ExampleBuild { - cargoarg: &Some("--quiet"), - example, - target, - features: features.clone(), - mode: BuildMode::Release, - }; - - if let Err(err) = command_parser(globals, &cmd, false) { - error!("{err}"); - } + examples_iter(examples) + .map(|example| { + let cmd = CargoCommand::ExampleBuild { + cargoarg: &Some("--quiet"), + example, + target, + features: features.clone(), + mode: BuildMode::Release, + }; - let cmd = CargoCommand::Qemu { - cargoarg, - example, - target, - features: features.clone(), - mode: BuildMode::Release, - }; + if let Err(err) = command_parser(globals, &cmd, false) { + error!("{err}"); + } - if let Err(err) = command_parser(globals, &cmd, overwrite) { - error!("{err}"); - } - }); + let cmd = CargoCommand::Qemu { + cargoarg, + example, + target, + features: features.clone(), + mode: BuildMode::Release, + }; - Ok(()) + (globals, cmd, overwrite) + }) + .run_and_coalesce() } /// Check the binary sizes of examples @@ -251,7 +366,7 @@ pub fn build_and_check_size( let target = backend.to_target(); let features = Some(target.and_features(backend.to_rtic_feature())); - examples.into_par_iter().for_each(|example| { + let runner = examples_iter(examples).map(|example| { // Make sure the requested example(s) are built let cmd = CargoCommand::ExampleBuild { cargoarg: &Some("--quiet"), @@ -272,10 +387,8 @@ pub fn build_and_check_size( mode: BuildMode::Release, arguments: arguments.clone(), }; - if let Err(err) = command_parser(globals, &cmd, false) { - error!("{err}"); - } + (globals, cmd, false) }); - Ok(()) + runner.run_and_coalesce() } -- cgit v1.2.3 From df69b35c250eff5858d6e994a9866be35b987a6e Mon Sep 17 00:00:00 2001 From: datdenkikniet Date: Sat, 15 Apr 2023 13:18:18 +0200 Subject: More housekeeping and making it work that bit better --- xtask/src/cargo_commands.rs | 24 ++++++++---------------- 1 file changed, 8 insertions(+), 16 deletions(-) (limited to 'xtask/src/cargo_commands.rs') diff --git a/xtask/src/cargo_commands.rs b/xtask/src/cargo_commands.rs index e88f31e..26fb314 100644 --- a/xtask/src/cargo_commands.rs +++ b/xtask/src/cargo_commands.rs @@ -60,18 +60,18 @@ fn handle_results(results: Vec) -> anyhow::Result<()> { if !stdout.is_empty() && !stderr.is_empty() { log::log!( level, - "Command output for {command}\nStdout:\n{stdout}\nStderr:\n{stderr}" + "Output for \"{command}\"\nStdout:\n{stdout}\nStderr:\n{stderr}" ); } else if !stdout.is_empty() { log::log!( level, - "Command output for {command}\nStdout:\n{}", + "Output for \"{command}\":\nStdout:\n{}", stdout.trim_end() ); } else if !stderr.is_empty() { log::log!( level, - "Command output for {command}\nStderr:\n{}", + "Output for \"{command}\"\nStderr:\n{}", stderr.trim_end() ); } @@ -82,15 +82,16 @@ fn handle_results(results: Vec) -> anyhow::Result<()> { errors.clone().for_each(log_stdout_stderr(Level::Error)); successes.for_each(|(cmd, _)| { - info!("Succesfully executed {cmd}"); + info!("Success: {cmd}"); }); errors.clone().for_each(|(cmd, _)| { - error!("Command {cmd} failed"); + error!("Failed: {cmd}"); }); - if errors.count() != 0 { - Err(anyhow::anyhow!("Some commands failed.")) + let ecount = errors.count(); + if ecount != 0 { + Err(anyhow::anyhow!("{ecount} commands failed.")) } else { Ok(()) } @@ -153,15 +154,6 @@ pub fn cargo( let features = package.extract_features(target, backend); - match operation { - BuildOrCheck::Check => { - log::debug!(target: "xtask::command", "Checking package: {package}") - } - BuildOrCheck::Build => { - log::debug!(target: "xtask::command", "Building package: {package}") - } - } - let command = match operation { BuildOrCheck::Check => CargoCommand::Check { cargoarg, -- cgit v1.2.3 From 461023e3b836db394dce0e034a1d329b1f5c8f48 Mon Sep 17 00:00:00 2001 From: datdenkikniet Date: Sat, 15 Apr 2023 13:45:58 +0200 Subject: More emojis and correct place for things --- xtask/src/cargo_commands.rs | 179 ++++++++++++++------------------------------ 1 file changed, 56 insertions(+), 123 deletions(-) (limited to 'xtask/src/cargo_commands.rs') diff --git a/xtask/src/cargo_commands.rs b/xtask/src/cargo_commands.rs index 26fb314..ec5fcfa 100644 --- a/xtask/src/cargo_commands.rs +++ b/xtask/src/cargo_commands.rs @@ -3,14 +3,14 @@ use crate::{ command::{BuildMode, CargoCommand}, command_parser, RunResult, }; -use log::{error, info, Level}; +use log::error; #[cfg(feature = "rayon")] use rayon::prelude::*; use iters::*; -enum FinalRunResult<'c> { +pub enum FinalRunResult<'c> { Success(CargoCommand<'c>, RunResult), Failed(CargoCommand<'c>, RunResult), CommandError(anyhow::Error), @@ -36,71 +36,10 @@ fn run_and_convert<'a>( } } -fn handle_results(results: Vec) -> anyhow::Result<()> { - let errors = results.iter().filter_map(|r| { - if let FinalRunResult::Failed(c, r) = r { - Some((c, r)) - } else { - None - } - }); - - let successes = results.iter().filter_map(|r| { - if let FinalRunResult::Success(c, r) = r { - Some((c, r)) - } else { - None - } - }); - - let log_stdout_stderr = |level: Level| { - move |(command, result): (&CargoCommand, &RunResult)| { - let stdout = &result.stdout; - let stderr = &result.stderr; - if !stdout.is_empty() && !stderr.is_empty() { - log::log!( - level, - "Output for \"{command}\"\nStdout:\n{stdout}\nStderr:\n{stderr}" - ); - } else if !stdout.is_empty() { - log::log!( - level, - "Output for \"{command}\":\nStdout:\n{}", - stdout.trim_end() - ); - } else if !stderr.is_empty() { - log::log!( - level, - "Output for \"{command}\"\nStderr:\n{}", - stderr.trim_end() - ); - } - } - }; - - successes.clone().for_each(log_stdout_stderr(Level::Debug)); - errors.clone().for_each(log_stdout_stderr(Level::Error)); - - successes.for_each(|(cmd, _)| { - info!("Success: {cmd}"); - }); - - errors.clone().for_each(|(cmd, _)| { - error!("Failed: {cmd}"); - }); - - let ecount = errors.count(); - if ecount != 0 { - Err(anyhow::anyhow!("{ecount} commands failed.")) - } else { - Ok(()) - } -} - -pub trait CoalescingRunning { +pub trait CoalescingRunner<'c> { /// Run all the commands in this iterator, and coalesce the results into /// one error (if any individual commands failed) - fn run_and_coalesce(self) -> anyhow::Result<()>; + fn run_and_coalesce(self) -> Vec>; } #[cfg(not(feature = "rayon"))] @@ -111,13 +50,12 @@ mod iters { examples.into_iter() } - impl<'g, 'c, I> CoalescingRunning for I + impl<'g, 'c, I> CoalescingRunner<'c> for I where I: Iterator, bool)>, { - fn run_and_coalesce(self) -> anyhow::Result<()> { - let results: Vec<_> = self.map(run_and_convert).collect(); - handle_results(results) + fn run_and_coalesce(self) -> Vec> { + self.map(run_and_convert).collect() } } } @@ -130,28 +68,26 @@ mod iters { examples.into_par_iter() } - impl<'g, 'c, I> CoalescingRunning for I + impl<'g, 'c, I> CoalescingRunner<'c> for I where I: ParallelIterator, bool)>, { - fn run_and_coalesce(self) -> anyhow::Result<()> { - let results: Vec<_> = self.map(run_and_convert).collect(); - handle_results(results) + fn run_and_coalesce(self) -> Vec> { + self.map(run_and_convert).collect() } } } /// Cargo command to either build or check -pub fn cargo( +pub fn cargo<'c>( globals: &Globals, operation: BuildOrCheck, - cargoarg: &Option<&str>, - package: &PackageOpt, + cargoarg: &'c Option<&'c str>, + package: &'c PackageOpt, backend: Backends, -) -> anyhow::Result<()> { - let runner = package.packages().map(|package| { +) -> Vec> { + let runner = package.packages().map(move |package| { let target = backend.to_target(); - let features = package.extract_features(target, backend); let command = match operation { @@ -180,13 +116,13 @@ pub fn cargo( /// Cargo command to either build or check all examples /// /// The examples are in rtic/examples -pub fn cargo_example( +pub fn cargo_example<'c>( globals: &Globals, operation: BuildOrCheck, - cargoarg: &Option<&str>, + cargoarg: &'c Option<&'c str>, backend: Backends, - examples: &[String], -) -> anyhow::Result<()> { + examples: &'c [String], +) -> Vec> { let runner = examples_iter(examples).map(|example| { let features = Some(backend.to_target().and_features(backend.to_rtic_feature())); @@ -212,12 +148,12 @@ pub fn cargo_example( } /// Run cargo clippy on selected package -pub fn cargo_clippy( +pub fn cargo_clippy<'c>( globals: &Globals, - cargoarg: &Option<&str>, - package: &PackageOpt, + cargoarg: &'c Option<&'c str>, + package: &'c PackageOpt, backend: Backends, -) -> anyhow::Result<()> { +) -> Vec> { let runner = package.packages().map(|p| { let target = backend.to_target(); let features = p.extract_features(target, backend); @@ -238,12 +174,12 @@ pub fn cargo_clippy( } /// Run cargo fmt on selected package -pub fn cargo_format( +pub fn cargo_format<'c>( globals: &Globals, - cargoarg: &Option<&str>, - package: &PackageOpt, + cargoarg: &'c Option<&'c str>, + package: &'c PackageOpt, check_only: bool, -) -> anyhow::Result<()> { +) -> Vec> { let runner = package.packages().map(|p| { ( globals, @@ -259,34 +195,31 @@ pub fn cargo_format( } /// Run cargo doc -pub fn cargo_doc( +pub fn cargo_doc<'c>( globals: &Globals, - cargoarg: &Option<&str>, + cargoarg: &'c Option<&'c str>, backend: Backends, - arguments: &Option, -) -> anyhow::Result<()> { + arguments: &'c Option, +) -> Vec> { let features = Some(backend.to_target().and_features(backend.to_rtic_feature())); - command_parser( - globals, - &CargoCommand::Doc { - cargoarg, - features, - arguments: arguments.clone(), - }, - false, - )?; - Ok(()) + let command = CargoCommand::Doc { + cargoarg, + features, + arguments: arguments.clone(), + }; + + vec![run_and_convert((globals, command, false))] } /// Run cargo test on the selected package or all packages /// /// If no package is specified, loop through all packages -pub fn cargo_test( +pub fn cargo_test<'c>( globals: &Globals, - package: &PackageOpt, + package: &'c PackageOpt, backend: Backends, -) -> anyhow::Result<()> { +) -> Vec> { package .packages() .map(|p| (globals, TestMetadata::match_package(p, backend), false)) @@ -294,29 +227,29 @@ pub fn cargo_test( } /// Use mdbook to build the book -pub fn cargo_book( +pub fn cargo_book<'c>( globals: &Globals, - arguments: &Option, -) -> anyhow::Result { - command_parser( + arguments: &'c Option, +) -> Vec> { + vec![run_and_convert(( globals, - &CargoCommand::Book { + CargoCommand::Book { arguments: arguments.clone(), }, false, - ) + ))] } /// Run examples /// /// Supports updating the expected output via the overwrite argument -pub fn run_test( +pub fn run_test<'c>( globals: &Globals, - cargoarg: &Option<&str>, + cargoarg: &'c Option<&'c str>, backend: Backends, - examples: &[String], + examples: &'c [String], overwrite: bool, -) -> anyhow::Result<()> { +) -> Vec> { let target = backend.to_target(); let features = Some(target.and_features(backend.to_rtic_feature())); @@ -348,13 +281,13 @@ pub fn run_test( } /// Check the binary sizes of examples -pub fn build_and_check_size( +pub fn build_and_check_size<'c>( globals: &Globals, - cargoarg: &Option<&str>, + cargoarg: &'c Option<&'c str>, backend: Backends, - examples: &[String], - arguments: &Option, -) -> anyhow::Result<()> { + examples: &'c [String], + arguments: &'c Option, +) -> Vec> { let target = backend.to_target(); let features = Some(target.and_features(backend.to_rtic_feature())); -- cgit v1.2.3 From feb00a9755ae8f96c8b761f288a6dad2eb41c5b1 Mon Sep 17 00:00:00 2001 From: datdenkikniet Date: Sat, 15 Apr 2023 14:28:24 +0200 Subject: Add support for "feature mixer" --- xtask/src/cargo_commands.rs | 96 ++++++++++++++++++++++++++++----------------- 1 file changed, 61 insertions(+), 35 deletions(-) (limited to 'xtask/src/cargo_commands.rs') diff --git a/xtask/src/cargo_commands.rs b/xtask/src/cargo_commands.rs index ec5fcfa..9cbdaef 100644 --- a/xtask/src/cargo_commands.rs +++ b/xtask/src/cargo_commands.rs @@ -86,29 +86,42 @@ pub fn cargo<'c>( package: &'c PackageOpt, backend: Backends, ) -> Vec> { - let runner = package.packages().map(move |package| { - let target = backend.to_target(); - let features = package.extract_features(target, backend); + let runner = package + .packages() + .flat_map(|package| { + let target = backend.to_target(); + let features = package.features(target, backend, globals.partial); - let command = match operation { - BuildOrCheck::Check => CargoCommand::Check { - cargoarg, - package: Some(package), - target, - features, - mode: BuildMode::Release, - }, - BuildOrCheck::Build => CargoCommand::Build { - cargoarg, - package: Some(package), - target, - features, - mode: BuildMode::Release, - }, - }; + #[cfg(feature = "rayon")] + { + features.into_par_iter().map(move |f| (package, target, f)) + } - (globals, command, false) - }); + #[cfg(not(feature = "rayon"))] + { + features.into_iter().map(move |f| (package, target, f)) + } + }) + .map(move |(package, target, features)| { + let command = match operation { + BuildOrCheck::Check => CargoCommand::Check { + cargoarg, + package: Some(package), + target, + features, + mode: BuildMode::Release, + }, + BuildOrCheck::Build => CargoCommand::Build { + cargoarg, + package: Some(package), + target, + features, + mode: BuildMode::Release, + }, + }; + + (globals, command, false) + }); runner.run_and_coalesce() } @@ -154,21 +167,34 @@ pub fn cargo_clippy<'c>( package: &'c PackageOpt, backend: Backends, ) -> Vec> { - let runner = package.packages().map(|p| { - let target = backend.to_target(); - let features = p.extract_features(target, backend); + let runner = package + .packages() + .flat_map(|package| { + let target = backend.to_target(); + let features = package.features(target, backend, globals.partial); - ( - globals, - CargoCommand::Clippy { - cargoarg, - package: Some(p), - target, - features, - }, - false, - ) - }); + #[cfg(feature = "rayon")] + { + features.into_par_iter().map(move |f| (package, target, f)) + } + + #[cfg(not(feature = "rayon"))] + { + features.into_iter().map(move |f| (package, target, f)) + } + }) + .map(move |(package, target, features)| { + ( + globals, + CargoCommand::Clippy { + cargoarg, + package: Some(package), + target, + features, + }, + false, + ) + }); runner.run_and_coalesce() } -- cgit v1.2.3