From fa92d8abe7810c8a32a37be49f162b795c226f4d Mon Sep 17 00:00:00 2001 From: datdenkikniet Date: Sat, 15 Apr 2023 00:09:50 +0200 Subject: [PATCH 01/17] Add some QoL to run_command --- xtask/Cargo.toml | 1 - xtask/src/command.rs | 35 +++++++++++++++++++---------------- xtask/src/main.rs | 6 +++++- 3 files changed, 24 insertions(+), 18 deletions(-) diff --git a/xtask/Cargo.toml b/xtask/Cargo.toml index 3c72bf1d3e..1e7247a949 100644 --- a/xtask/Cargo.toml +++ b/xtask/Cargo.toml @@ -6,7 +6,6 @@ publish = false [dependencies] anyhow = "1.0.43" -os_pipe = "1.1.2" clap = { version = "4", features = ["derive"] } env_logger = "0.10.0" log = "0.4.17" diff --git a/xtask/src/command.rs b/xtask/src/command.rs index 6e91a527a2..8a2e99b738 100644 --- a/xtask/src/command.rs +++ b/xtask/src/command.rs @@ -1,7 +1,10 @@ use crate::{debug, ExtraArguments, Package, RunResult, TestRunError}; use core::fmt; -use os_pipe::pipe; -use std::{fs::File, io::Read, process::Command}; +use std::{ + fs::File, + io::Read, + process::{Command, Stdio}, +}; #[allow(dead_code)] #[derive(Debug, Clone, Copy, PartialEq)] @@ -412,26 +415,26 @@ impl fmt::Display for BuildMode { } pub fn run_command(command: &CargoCommand) -> anyhow::Result { - let (mut reader, writer) = pipe()?; - let (mut error_reader, error_writer) = pipe()?; - debug!("👟 {} {}", command.executable(), command.args().join(" ")); + let command_display = command.executable(); + let args = command.args(); - let mut handle = Command::new(command.executable()) + let full_command = format!("\"{command_display}\" {}", args.join(" ")); + + debug!("👟 {full_command}"); + + let result = Command::new(command.executable()) .args(command.args()) - .stdout(writer) - .stderr(error_writer) - .spawn()?; + .stdout(Stdio::piped()) + .stderr(Stdio::piped()) + .output()?; - // retrieve output and clean up - let mut stdout = String::new(); - reader.read_to_string(&mut stdout)?; - let exit_status = handle.wait()?; - - let mut stderr = String::new(); - error_reader.read_to_string(&mut stderr)?; + let exit_status = result.status; + let stderr = String::from_utf8(result.stderr).unwrap_or("Not displayable".into()); + let stdout = String::from_utf8(result.stdout).unwrap_or("Not displayable".into()); Ok(RunResult { exit_status, + full_command, stdout, stderr, }) diff --git a/xtask/src/main.rs b/xtask/src/main.rs index a7fd1d3229..30608b94b3 100644 --- a/xtask/src/main.rs +++ b/xtask/src/main.rs @@ -44,6 +44,7 @@ const DEFAULT_FEATURES: &str = "test-critical-section"; #[derive(Debug, Clone)] pub struct RunResult { exit_status: ExitStatus, + full_command: String, stdout: String, stderr: String, } @@ -329,9 +330,12 @@ fn command_parser(command: &CargoCommand, overwrite: bool) -> anyhow::Result<()> | CargoCommand::Book { .. } | CargoCommand::ExampleSize { .. } => { let cargo_result = run_command(command)?; + let command = cargo_result.full_command; if let Some(exit_code) = cargo_result.exit_status.code() { if exit_code != exitcode::OK { - error!("Exit code from command: {exit_code}"); + error!("Command {command} failed."); + error!("Exit code: {exit_code}"); + if !cargo_result.stdout.is_empty() { info!("{}", cargo_result.stdout); } From 18522122f1238d7200a9c4bcc696e707385bcbb1 Mon Sep 17 00:00:00 2001 From: datdenkikniet Date: Sat, 15 Apr 2023 00:26:16 +0200 Subject: [PATCH 02/17] xtask: forward globals through the chain and add stderr-inheritance flag --- xtask/src/argument_parsing.rs | 30 +++++++++++++------ xtask/src/cargo_commands.rs | 39 ++++++++++++++++++------- xtask/src/command.rs | 19 ++++++++++-- xtask/src/main.rs | 54 +++++++++++++++++++++++------------ 4 files changed, 103 insertions(+), 39 deletions(-) diff --git a/xtask/src/argument_parsing.rs b/xtask/src/argument_parsing.rs index c0538e204e..eda0a89c24 100644 --- a/xtask/src/argument_parsing.rs +++ b/xtask/src/argument_parsing.rs @@ -130,10 +130,8 @@ pub enum BuildOrCheck { Build, } -#[derive(Parser)] -#[command(author, version, about, long_about = None)] -/// RTIC xtask powered testing toolbox -pub struct Cli { +#[derive(Parser, Clone)] +pub struct Globals { /// For which backend to build (defaults to thumbv7) #[arg(value_enum, short, long)] pub backend: Option, @@ -160,12 +158,28 @@ pub struct Cli { #[arg(short, long, action = clap::ArgAction::Count)] pub verbose: u8, + /// Enable `stderr` inheritance on child processes. + /// + /// If this flag is enabled, the output of `stderr` produced by child + /// processes is printed directly to `stderr`. This will cause a lot of + /// clutter, but can make debugging long-running processes a lot easier. + #[arg(short, long)] + pub stderr_inherited: bool, +} + +#[derive(Parser)] +#[command(author, version, about, long_about = None)] +/// RTIC xtask powered testing toolbox +pub struct Cli { + #[clap(flatten)] + pub globals: Globals, + /// Subcommand selecting operation #[command(subcommand)] pub command: Commands, } -#[derive(Debug, Subcommand)] +#[derive(Debug, Clone, Subcommand)] pub enum Commands { /// Check formatting FormatCheck(PackageOpt), @@ -227,7 +241,7 @@ pub enum Commands { Book(Arg), } -#[derive(Args, Debug)] +#[derive(Args, Debug, Clone)] /// Restrict to package, or run on whole workspace pub struct PackageOpt { /// For which package/workspace member to operate @@ -236,7 +250,7 @@ pub struct PackageOpt { pub package: Option, } -#[derive(Args, Debug)] +#[derive(Args, Debug, Clone)] pub struct QemuAndRun { /// If expected output is missing or mismatching, recreate the file /// @@ -245,7 +259,7 @@ pub struct QemuAndRun { pub overwrite_expected: bool, } -#[derive(Debug, Parser)] +#[derive(Debug, Parser, Clone)] pub struct Arg { /// Options to pass to `cargo size` #[command(subcommand)] diff --git a/xtask/src/cargo_commands.rs b/xtask/src/cargo_commands.rs index 7ac7aea964..90a803776a 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}"); } }); diff --git a/xtask/src/command.rs b/xtask/src/command.rs index 8a2e99b738..9fa5378dc4 100644 --- a/xtask/src/command.rs +++ b/xtask/src/command.rs @@ -13,6 +13,21 @@ pub enum BuildMode { Debug, } +#[derive(Debug, Clone, Copy, PartialEq)] +pub enum OutputMode { + PipedAndCollected, + Inherited, +} + +impl From for Stdio { + fn from(value: OutputMode) -> Self { + match value { + OutputMode::PipedAndCollected => Stdio::piped(), + OutputMode::Inherited => Stdio::inherit(), + } + } +} + #[derive(Debug)] pub enum CargoCommand<'a> { // For future embedded-ci @@ -414,7 +429,7 @@ impl fmt::Display for BuildMode { } } -pub fn run_command(command: &CargoCommand) -> anyhow::Result { +pub fn run_command(command: &CargoCommand, stderr_mode: OutputMode) -> anyhow::Result { let command_display = command.executable(); let args = command.args(); @@ -425,7 +440,7 @@ pub fn run_command(command: &CargoCommand) -> anyhow::Result { let result = Command::new(command.executable()) .args(command.args()) .stdout(Stdio::piped()) - .stderr(Stdio::piped()) + .stderr(stderr_mode) .output()?; let exit_status = result.status; diff --git a/xtask/src/main.rs b/xtask/src/main.rs index 30608b94b3..4cb38c2ece 100644 --- a/xtask/src/main.rs +++ b/xtask/src/main.rs @@ -4,8 +4,9 @@ mod cargo_commands; mod command; use anyhow::bail; -use argument_parsing::{ExtraArguments, Package}; +use argument_parsing::{ExtraArguments, Globals, Package}; use clap::Parser; +use command::OutputMode; use core::fmt; use diffy::{create_patch, PatchFormatter}; use std::{ @@ -109,7 +110,9 @@ fn main() -> anyhow::Result<()> { let cli = Cli::parse(); - let env_logger_default_level = match cli.verbose { + let globals = &cli.globals; + + let env_logger_default_level = match globals.verbose { 0 => Env::default().default_filter_or("info"), 1 => Env::default().default_filter_or("debug"), _ => Env::default().default_filter_or("trace"), @@ -119,16 +122,16 @@ fn main() -> anyhow::Result<()> { .format_timestamp(None) .init(); - trace!("default logging level: {0}", cli.verbose); + trace!("default logging level: {0}", globals.verbose); - let backend = if let Some(backend) = cli.backend { + let backend = if let Some(backend) = globals.backend { backend } else { Backends::default() }; - let example = cli.example; - let exampleexclude = cli.exampleexclude; + let example = globals.example.clone(); + let exampleexclude = globals.exampleexclude.clone(); let examples_to_run = { let mut examples_to_run = examples.clone(); @@ -190,28 +193,29 @@ fn main() -> anyhow::Result<()> { Commands::FormatCheck(args) => { info!("Running cargo fmt --check: {args:?}"); let check_only = true; - cargo_format(&cargologlevel, &args, check_only)?; + cargo_format(globals, &cargologlevel, &args, check_only)?; } Commands::Format(args) => { info!("Running cargo fmt: {args:?}"); let check_only = false; - cargo_format(&cargologlevel, &args, check_only)?; + cargo_format(globals, &cargologlevel, &args, check_only)?; } Commands::Clippy(args) => { info!("Running clippy on backend: {backend:?}"); - cargo_clippy(&cargologlevel, &args, backend)?; + cargo_clippy(globals, &cargologlevel, &args, backend)?; } Commands::Check(args) => { info!("Checking on backend: {backend:?}"); - cargo(BuildOrCheck::Check, &cargologlevel, &args, backend)?; + cargo(globals, BuildOrCheck::Check, &cargologlevel, &args, backend)?; } Commands::Build(args) => { info!("Building for backend: {backend:?}"); - cargo(BuildOrCheck::Build, &cargologlevel, &args, backend)?; + cargo(globals, BuildOrCheck::Build, &cargologlevel, &args, backend)?; } Commands::ExampleCheck => { info!("Checking on backend: {backend:?}"); cargo_example( + globals, BuildOrCheck::Check, &cargologlevel, backend, @@ -221,6 +225,7 @@ fn main() -> anyhow::Result<()> { Commands::ExampleBuild => { info!("Building for backend: {backend:?}"); cargo_example( + globals, BuildOrCheck::Build, &cargologlevel, backend, @@ -230,12 +235,19 @@ fn main() -> anyhow::Result<()> { Commands::Size(args) => { // x86_64 target not valid info!("Measuring for backend: {backend:?}"); - build_and_check_size(&cargologlevel, backend, &examples_to_run, &args.arguments)?; + build_and_check_size( + globals, + &cargologlevel, + backend, + &examples_to_run, + &args.arguments, + )?; } Commands::Qemu(args) | Commands::Run(args) => { // x86_64 target not valid info!("Testing for backend: {backend:?}"); run_test( + globals, &cargologlevel, backend, &examples_to_run, @@ -244,15 +256,15 @@ fn main() -> anyhow::Result<()> { } Commands::Doc(args) => { info!("Running cargo doc on backend: {backend:?}"); - cargo_doc(&cargologlevel, backend, &args.arguments)?; + cargo_doc(globals, &cargologlevel, backend, &args.arguments)?; } Commands::Test(args) => { info!("Running cargo test on backend: {backend:?}"); - cargo_test(&args, backend)?; + cargo_test(globals, &args, backend)?; } Commands::Book(args) => { info!("Running mdbook"); - cargo_book(&args.arguments)?; + cargo_book(globals, &args.arguments)?; } } @@ -283,7 +295,13 @@ fn package_feature_extractor(package: &PackageOpt, backend: Backends) -> Option< } // run example binary `example` -fn command_parser(command: &CargoCommand, overwrite: bool) -> anyhow::Result<()> { +fn command_parser(glob: &Globals, command: &CargoCommand, overwrite: bool) -> anyhow::Result<()> { + let output_mode = if glob.stderr_inherited { + OutputMode::Inherited + } else { + OutputMode::PipedAndCollected + }; + match *command { CargoCommand::Qemu { example, .. } | CargoCommand::Run { example, .. } => { let run_file = format!("{example}.run"); @@ -296,7 +314,7 @@ fn command_parser(command: &CargoCommand, overwrite: bool) -> anyhow::Result<()> // cargo run <..> info!("Running example: {example}"); - let cargo_run_result = run_command(command)?; + let cargo_run_result = run_command(command, output_mode)?; info!("{}", cargo_run_result.stdout); // Create a file for the expected output if it does not exist or mismatches @@ -329,7 +347,7 @@ fn command_parser(command: &CargoCommand, overwrite: bool) -> anyhow::Result<()> | CargoCommand::Test { .. } | CargoCommand::Book { .. } | CargoCommand::ExampleSize { .. } => { - let cargo_result = run_command(command)?; + let cargo_result = run_command(command, output_mode)?; let command = cargo_result.full_command; if let Some(exit_code) = cargo_result.exit_status.code() { if exit_code != exitcode::OK { From 4adae80f2d575b631b0bc1aef4b7272e62acedb6 Mon Sep 17 00:00:00 2001 From: datdenkikniet Date: Sat, 15 Apr 2023 00:50:46 +0200 Subject: [PATCH 03/17] xtask: don't add default arguments if building for a no_std target --- xtask/src/argument_parsing.rs | 14 ++++---- xtask/src/cargo_commands.rs | 64 +++++++++++++---------------------- xtask/src/command.rs | 60 ++++++++++++++++++++++++-------- xtask/src/main.rs | 55 +++++++++++++++++++++++------- 4 files changed, 118 insertions(+), 75 deletions(-) diff --git a/xtask/src/argument_parsing.rs b/xtask/src/argument_parsing.rs index eda0a89c24..f643cbb610 100644 --- a/xtask/src/argument_parsing.rs +++ b/xtask/src/argument_parsing.rs @@ -1,4 +1,4 @@ -use crate::{command::CargoCommand, ARMV6M, ARMV7M, ARMV8MBASE, ARMV8MMAIN, DEFAULT_FEATURES}; +use crate::{command::CargoCommand, Target, ARMV6M, ARMV7M, ARMV8MBASE, ARMV8MMAIN}; use clap::{Args, Parser, Subcommand}; use core::fmt; @@ -37,12 +37,12 @@ impl TestMetadata { pub fn match_package(package: Package, backend: Backends) -> CargoCommand<'static> { match package { Package::Rtic => { - let features = Some(format!( - "{},{},{}", - DEFAULT_FEATURES, + let features = format!( + "{},{}", backend.to_rtic_feature(), - backend.to_rtic_uitest_feature(), - )); + backend.to_rtic_uitest_feature() + ); + let features = Some(backend.to_target().and_features(&features)); CargoCommand::Test { package: Some(package), features, @@ -89,7 +89,7 @@ pub enum Backends { impl Backends { #[allow(clippy::wrong_self_convention)] - pub fn to_target(&self) -> &str { + pub fn to_target(&self) -> Target { match self { Backends::Thumbv6 => ARMV6M, Backends::Thumbv7 => ARMV7M, diff --git a/xtask/src/cargo_commands.rs b/xtask/src/cargo_commands.rs index 90a803776a..af6114187f 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(), }; diff --git a/xtask/src/command.rs b/xtask/src/command.rs index 9fa5378dc4..32ca9c854d 100644 --- a/xtask/src/command.rs +++ b/xtask/src/command.rs @@ -1,4 +1,4 @@ -use crate::{debug, ExtraArguments, Package, RunResult, TestRunError}; +use crate::{debug, ExtraArguments, Package, RunResult, Target, TestRunError}; use core::fmt; use std::{ fs::File, @@ -35,49 +35,49 @@ pub enum CargoCommand<'a> { Run { cargoarg: &'a Option<&'a str>, example: &'a str, - target: &'a str, + target: Target<'a>, features: Option, mode: BuildMode, }, Qemu { cargoarg: &'a Option<&'a str>, example: &'a str, - target: &'a str, + target: Target<'a>, features: Option, mode: BuildMode, }, ExampleBuild { cargoarg: &'a Option<&'a str>, example: &'a str, - target: &'a str, + target: Target<'a>, features: Option, mode: BuildMode, }, ExampleCheck { cargoarg: &'a Option<&'a str>, example: &'a str, - target: &'a str, + target: Target<'a>, features: Option, mode: BuildMode, }, Build { cargoarg: &'a Option<&'a str>, package: Option, - target: &'a str, + target: Target<'a>, features: Option, mode: BuildMode, }, Check { cargoarg: &'a Option<&'a str>, package: Option, - target: &'a str, + target: Target<'a>, features: Option, mode: BuildMode, }, Clippy { cargoarg: &'a Option<&'a str>, package: Option, - target: &'a str, + target: Target<'a>, features: Option, }, Format { @@ -101,7 +101,7 @@ pub enum CargoCommand<'a> { ExampleSize { cargoarg: &'a Option<&'a str>, example: &'a str, - target: &'a str, + target: Target<'a>, features: Option, mode: BuildMode, arguments: Option, @@ -153,7 +153,13 @@ impl<'a> CargoCommand<'a> { if let Some(cargoarg) = cargoarg { args.extend_from_slice(&[cargoarg]); } - args.extend_from_slice(&[self.command(), "--example", example, "--target", target]); + args.extend_from_slice(&[ + self.command(), + "--example", + example, + "--target", + target.triple(), + ]); if let Some(feature) = features { args.extend_from_slice(&["--features", feature]); @@ -174,7 +180,13 @@ impl<'a> CargoCommand<'a> { if let Some(cargoarg) = cargoarg { args.extend_from_slice(&[cargoarg]); } - args.extend_from_slice(&[self.command(), "--example", example, "--target", target]); + args.extend_from_slice(&[ + self.command(), + "--example", + example, + "--target", + target.triple(), + ]); if let Some(feature) = features { args.extend_from_slice(&["--features", feature]); @@ -196,7 +208,7 @@ impl<'a> CargoCommand<'a> { args.extend_from_slice(&[cargoarg]); } - args.extend_from_slice(&[self.command(), "--target", target]); + args.extend_from_slice(&[self.command(), "--target", target.triple()]); if let Some(package) = package { args.extend_from_slice(&["--package", package.name()]); @@ -344,7 +356,13 @@ impl<'a> CargoCommand<'a> { if let Some(cargoarg) = cargoarg { args.extend_from_slice(&[cargoarg]); } - args.extend_from_slice(&[self.command(), "--example", example, "--target", target]); + args.extend_from_slice(&[ + self.command(), + "--example", + example, + "--target", + target.triple(), + ]); if let Some(feature) = features { args.extend_from_slice(&["--features", feature]); @@ -365,7 +383,13 @@ impl<'a> CargoCommand<'a> { if let Some(cargoarg) = cargoarg { args.extend_from_slice(&[cargoarg]); } - args.extend_from_slice(&[self.command(), "--example", example, "--target", target]); + args.extend_from_slice(&[ + self.command(), + "--example", + example, + "--target", + target.triple(), + ]); if let Some(feature) = features { args.extend_from_slice(&["--features", feature]); @@ -387,7 +411,13 @@ impl<'a> CargoCommand<'a> { if let Some(cargoarg) = cargoarg { args.extend_from_slice(&[cargoarg]); } - args.extend_from_slice(&[self.command(), "--example", example, "--target", target]); + args.extend_from_slice(&[ + self.command(), + "--example", + example, + "--target", + target.triple(), + ]); if let Some(feature_name) = features { args.extend_from_slice(&["--features", feature_name]); diff --git a/xtask/src/main.rs b/xtask/src/main.rs index 4cb38c2ece..8f6a556971 100644 --- a/xtask/src/main.rs +++ b/xtask/src/main.rs @@ -33,14 +33,42 @@ use crate::{ command::{run_command, run_successful, CargoCommand}, }; -// x86_64-unknown-linux-gnu -const _X86_64: &str = "x86_64-unknown-linux-gnu"; -const ARMV6M: &str = "thumbv6m-none-eabi"; -const ARMV7M: &str = "thumbv7m-none-eabi"; -const ARMV8MBASE: &str = "thumbv8m.base-none-eabi"; -const ARMV8MMAIN: &str = "thumbv8m.main-none-eabi"; +#[derive(Debug, Clone, Copy)] +pub struct Target<'a> { + triple: &'a str, + has_std: bool, +} -const DEFAULT_FEATURES: &str = "test-critical-section"; +impl<'a> Target<'a> { + const STD_FEATURES: &str = "test-critical-section"; + + pub const fn new(triple: &'a str, has_std: bool) -> Self { + Self { triple, has_std } + } + + pub fn triple(&self) -> &str { + self.triple + } + + pub fn has_std(&self) -> bool { + self.has_std + } + + pub fn and_features(&self, features: &str) -> String { + if self.has_std { + format!("{},{}", Self::STD_FEATURES, features) + } else { + features.to_string() + } + } +} + +// x86_64-unknown-linux-gnu +const _X86_64: Target = Target::new("x86_64-unknown-linux-gnu", true); +const ARMV6M: Target = Target::new("thumbv6m-none-eabi", false); +const ARMV7M: Target = Target::new("thumbv7m-none-eabi", false); +const ARMV8MBASE: Target = Target::new("thumbv8m.base-none-eabi", false); +const ARMV8MMAIN: Target = Target::new("thumbv8m.main-none-eabi", false); #[derive(Debug, Clone)] pub struct RunResult { @@ -276,12 +304,13 @@ fn main() -> anyhow::Result<()> { /// Without package specified the features for RTIC are required /// With only a single package which is not RTIC, no special /// features are needed -fn package_feature_extractor(package: &PackageOpt, backend: Backends) -> Option { - let default_features = Some(format!( - "{},{}", - DEFAULT_FEATURES, - backend.to_rtic_feature() - )); +fn package_feature_extractor( + target: Target, + package: &PackageOpt, + backend: Backends, +) -> Option { + let default_features = Some(target.and_features(backend.to_rtic_feature())); + if let Some(package) = package.package { debug!("\nTesting package: {package}"); match package { From f2115e3d474ac9b3c802e162af3dbec620598c4e Mon Sep 17 00:00:00 2001 From: datdenkikniet Date: Sat, 15 Apr 2023 00:54:24 +0200 Subject: [PATCH 04/17] Unbrick `cargo xtask build` --- Cargo.toml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Cargo.toml b/Cargo.toml index 888a6eecc9..98ecfea66e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,4 +1,7 @@ [workspace] +default-members = [ + "rtic", +] members = [ "rtic", "rtic-sync", From 480aa210594a1ea808da93614aa49a508f9f35af Mon Sep 17 00:00:00 2001 From: datdenkikniet Date: Sat, 15 Apr 2023 10:03:52 +0200 Subject: [PATCH 05/17] Always run stuff for all packages if none is specified --- xtask/src/argument_parsing.rs | 35 +++++++- xtask/src/cargo_commands.rs | 149 ++++++++++++++++++---------------- xtask/src/main.rs | 26 +----- 3 files changed, 115 insertions(+), 95 deletions(-) diff --git a/xtask/src/argument_parsing.rs b/xtask/src/argument_parsing.rs index f643cbb610..7284fc553e 100644 --- a/xtask/src/argument_parsing.rs +++ b/xtask/src/argument_parsing.rs @@ -29,6 +29,30 @@ impl Package { Package::RticTime => "rtic-time", } } + + pub fn all() -> Vec { + vec![ + Self::Rtic, + Self::RticCommon, + Self::RticMacros, + Self::RticMonotonics, + Self::RticSync, + Self::RticTime, + ] + } + + /// Get the features needed given the selected package + /// + /// Without package specified the features for RTIC are required + /// With only a single package which is not RTIC, no special + /// features are needed + pub fn extract_features(&self, target: Target, backend: Backends) -> Option { + match self { + Package::Rtic => Some(target.and_features(backend.to_rtic_feature())), + Package::RticMacros => Some(backend.to_rtic_macros_feature().to_owned()), + _ => None, + } + } } pub struct TestMetadata {} @@ -247,7 +271,16 @@ pub struct PackageOpt { /// For which package/workspace member to operate /// /// If omitted, work on all - pub package: Option, + package: Option, +} + +impl PackageOpt { + pub fn packages(&self) -> impl Iterator { + self.package + .map(|p| vec![p]) + .unwrap_or(Package::all()) + .into_iter() + } } #[derive(Args, Debug, Clone)] diff --git a/xtask/src/cargo_commands.rs b/xtask/src/cargo_commands.rs index af6114187f..2a15b3c163 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}"); } diff --git a/xtask/src/main.rs b/xtask/src/main.rs index 8f6a556971..f2d01809ba 100644 --- a/xtask/src/main.rs +++ b/xtask/src/main.rs @@ -24,7 +24,7 @@ use env_logger::Env; use log::{debug, error, info, log_enabled, trace, Level}; use crate::{ - argument_parsing::{Backends, BuildOrCheck, Cli, Commands, PackageOpt}, + argument_parsing::{Backends, BuildOrCheck, Cli, Commands}, build::init_build_dir, cargo_commands::{ build_and_check_size, cargo, cargo_book, cargo_clippy, cargo_doc, cargo_example, @@ -299,30 +299,6 @@ fn main() -> anyhow::Result<()> { Ok(()) } -/// Get the features needed given the selected package -/// -/// Without package specified the features for RTIC are required -/// With only a single package which is not RTIC, no special -/// features are needed -fn package_feature_extractor( - target: Target, - package: &PackageOpt, - backend: Backends, -) -> Option { - let default_features = Some(target.and_features(backend.to_rtic_feature())); - - if let Some(package) = package.package { - debug!("\nTesting package: {package}"); - match package { - Package::Rtic => default_features, - Package::RticMacros => Some(backend.to_rtic_macros_feature().to_owned()), - _ => None, - } - } else { - default_features - } -} - // run example binary `example` fn command_parser(glob: &Globals, command: &CargoCommand, overwrite: bool) -> anyhow::Result<()> { let output_mode = if glob.stderr_inherited { From 1ccca03a70b5d11dc03c046041138f73267af22a Mon Sep 17 00:00:00 2001 From: datdenkikniet Date: Sat, 15 Apr 2023 10:10:04 +0200 Subject: [PATCH 06/17] Use pretty_env_logger instead --- xtask/Cargo.toml | 2 +- xtask/src/main.rs | 13 ++++++------- 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/xtask/Cargo.toml b/xtask/Cargo.toml index 1e7247a949..5609480bfa 100644 --- a/xtask/Cargo.toml +++ b/xtask/Cargo.toml @@ -7,7 +7,7 @@ publish = false [dependencies] anyhow = "1.0.43" clap = { version = "4", features = ["derive"] } -env_logger = "0.10.0" +pretty_env_logger = "0.4.0" log = "0.4.17" rayon = "1.6.1" diffy = "0.3.0" diff --git a/xtask/src/main.rs b/xtask/src/main.rs index f2d01809ba..89ca0feb1f 100644 --- a/xtask/src/main.rs +++ b/xtask/src/main.rs @@ -20,7 +20,6 @@ use std::{ str, }; -use env_logger::Env; use log::{debug, error, info, log_enabled, trace, Level}; use crate::{ @@ -141,13 +140,13 @@ fn main() -> anyhow::Result<()> { let globals = &cli.globals; let env_logger_default_level = match globals.verbose { - 0 => Env::default().default_filter_or("info"), - 1 => Env::default().default_filter_or("debug"), - _ => Env::default().default_filter_or("trace"), + 0 => "info", + 1 => "debug", + _ => "trace", }; - env_logger::Builder::from_env(env_logger_default_level) - .format_module_path(false) - .format_timestamp(None) + + pretty_env_logger::formatted_builder() + .parse_filters(&std::env::var("RUST_LOG").unwrap_or(env_logger_default_level.into())) .init(); trace!("default logging level: {0}", globals.verbose); From 525703358bf52b74a01d9b0c04680d33621d60cd Mon Sep 17 00:00:00 2001 From: datdenkikniet Date: Sat, 15 Apr 2023 12:21:11 +0200 Subject: [PATCH 07/17] Rework command execution structure and make rayon optional (since it's not necessarily faster due to workspace wide lockfile contention) --- .cargo/config.toml | 3 +- xtask/Cargo.toml | 3 +- xtask/src/argument_parsing.rs | 10 ++ xtask/src/cargo_commands.rs | 261 ++++++++++++++++++++++++---------- xtask/src/command.rs | 16 ++- xtask/src/main.rs | 47 ++---- 6 files changed, 223 insertions(+), 117 deletions(-) diff --git a/.cargo/config.toml b/.cargo/config.toml index d70faef427..0a62466ad2 100644 --- a/.cargo/config.toml +++ b/.cargo/config.toml @@ -1,5 +1,6 @@ [alias] xtask = "run --package xtask --" +pxtask = "run --package xtask --features rayon --" [target.thumbv6m-none-eabi] runner = "qemu-system-arm -cpu cortex-m3 -machine lm3s6965evb -nographic -semihosting-config enable=on,target=native -kernel" @@ -10,4 +11,4 @@ runner = "qemu-system-arm -cpu cortex-m3 -machine lm3s6965evb -nographic -semiho [target.'cfg(all(target_arch = "arm", target_os = "none"))'] rustflags = [ "-C", "link-arg=-Tlink.x", -] \ No newline at end of file +] diff --git a/xtask/Cargo.toml b/xtask/Cargo.toml index 5609480bfa..9e565fa470 100644 --- a/xtask/Cargo.toml +++ b/xtask/Cargo.toml @@ -9,6 +9,5 @@ anyhow = "1.0.43" clap = { version = "4", features = ["derive"] } pretty_env_logger = "0.4.0" log = "0.4.17" -rayon = "1.6.1" +rayon = { version = "1.6.1", optional = true } diffy = "0.3.0" -exitcode = "1.1.2" diff --git a/xtask/src/argument_parsing.rs b/xtask/src/argument_parsing.rs index 7284fc553e..e653f9a0ec 100644 --- a/xtask/src/argument_parsing.rs +++ b/xtask/src/argument_parsing.rs @@ -275,12 +275,22 @@ pub struct PackageOpt { } impl PackageOpt { + #[cfg(not(feature = "rayon"))] pub fn packages(&self) -> impl Iterator { self.package .map(|p| vec![p]) .unwrap_or(Package::all()) .into_iter() } + + #[cfg(feature = "rayon")] + pub fn packages(&self) -> impl rayon::prelude::ParallelIterator { + use rayon::prelude::*; + self.package + .map(|p| vec![p]) + .unwrap_or(Package::all()) + .into_par_iter() + } } #[derive(Args, Debug, Clone)] diff --git a/xtask/src/cargo_commands.rs b/xtask/src/cargo_commands.rs index 2a15b3c163..e88f31e970 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, - }; + examples_iter(examples) + .map(|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}"); - } + if let Err(err) = command_parser(globals, &cmd, false) { + error!("{err}"); + } - let cmd = CargoCommand::Qemu { - cargoarg, - 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, overwrite) { - error!("{err}"); - } - }); - - 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() } diff --git a/xtask/src/command.rs b/xtask/src/command.rs index 32ca9c854d..359a7f9fd0 100644 --- a/xtask/src/command.rs +++ b/xtask/src/command.rs @@ -108,6 +108,14 @@ pub enum CargoCommand<'a> { }, } +impl core::fmt::Display for CargoCommand<'_> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + let executable = self.executable(); + let args = self.args().join(" "); + write!(f, "\"{executable} {args}\"") + } +} + impl<'a> CargoCommand<'a> { fn command(&self) -> &str { match self { @@ -460,12 +468,7 @@ impl fmt::Display for BuildMode { } pub fn run_command(command: &CargoCommand, stderr_mode: OutputMode) -> anyhow::Result { - let command_display = command.executable(); - let args = command.args(); - - let full_command = format!("\"{command_display}\" {}", args.join(" ")); - - debug!("👟 {full_command}"); + debug!("👟 {command}"); let result = Command::new(command.executable()) .args(command.args()) @@ -479,7 +482,6 @@ pub fn run_command(command: &CargoCommand, stderr_mode: OutputMode) -> anyhow::R Ok(RunResult { exit_status, - full_command, stdout, stderr, }) diff --git a/xtask/src/main.rs b/xtask/src/main.rs index 89ca0feb1f..a50657d0a2 100644 --- a/xtask/src/main.rs +++ b/xtask/src/main.rs @@ -3,7 +3,6 @@ mod build; mod cargo_commands; mod command; -use anyhow::bail; use argument_parsing::{ExtraArguments, Globals, Package}; use clap::Parser; use command::OutputMode; @@ -15,7 +14,6 @@ use std::{ fs::File, io::prelude::*, path::{Path, PathBuf}, - process, process::ExitStatus, str, }; @@ -72,7 +70,6 @@ const ARMV8MMAIN: Target = Target::new("thumbv8m.main-none-eabi", false); #[derive(Debug, Clone)] pub struct RunResult { exit_status: ExitStatus, - full_command: String, stdout: String, stderr: String, } @@ -125,7 +122,9 @@ fn main() -> anyhow::Result<()> { // check the name of `env::current_dir()` because people might clone it into a different name) let probably_running_from_repo_root = Path::new("./xtask").exists(); if !probably_running_from_repo_root { - bail!("xtasks can only be executed from the root of the `rtic` repository"); + return Err(anyhow::anyhow!( + "xtasks can only be executed from the root of the `rtic` repository" + )); } let examples: Vec<_> = std::fs::read_dir("./rtic/examples")? @@ -195,10 +194,10 @@ fn main() -> anyhow::Result<()> { \n{examples:#?}\n\ By default if example flag is emitted, all examples are tested.", ); - process::exit(exitcode::USAGE); + return Err(anyhow::anyhow!("Incorrect usage")); } else { + examples_to_run } - examples_to_run }; init_build_dir()?; @@ -299,7 +298,11 @@ fn main() -> anyhow::Result<()> { } // run example binary `example` -fn command_parser(glob: &Globals, command: &CargoCommand, overwrite: bool) -> anyhow::Result<()> { +fn command_parser( + glob: &Globals, + command: &CargoCommand, + overwrite: bool, +) -> anyhow::Result { let output_mode = if glob.stderr_inherited { OutputMode::Inherited } else { @@ -338,8 +341,9 @@ fn command_parser(glob: &Globals, command: &CargoCommand, overwrite: bool) -> an }; } else { run_successful(&cargo_run_result, &expected_output_file)?; - } - Ok(()) + }; + + Ok(cargo_run_result) } CargoCommand::Format { .. } | CargoCommand::ExampleCheck { .. } @@ -352,30 +356,7 @@ fn command_parser(glob: &Globals, command: &CargoCommand, overwrite: bool) -> an | CargoCommand::Book { .. } | CargoCommand::ExampleSize { .. } => { let cargo_result = run_command(command, output_mode)?; - let command = cargo_result.full_command; - if let Some(exit_code) = cargo_result.exit_status.code() { - if exit_code != exitcode::OK { - error!("Command {command} failed."); - error!("Exit code: {exit_code}"); - - if !cargo_result.stdout.is_empty() { - info!("{}", cargo_result.stdout); - } - if !cargo_result.stderr.is_empty() { - error!("{}", cargo_result.stderr); - } - process::exit(exit_code); - } else { - if !cargo_result.stdout.is_empty() { - info!("{}", cargo_result.stdout); - } - if !cargo_result.stderr.is_empty() { - info!("{}", cargo_result.stderr); - } - } - } - - Ok(()) + Ok(cargo_result) } } } From 3458288946a7243bdf94cee8e5a75e30663cd35b Mon Sep 17 00:00:00 2001 From: datdenkikniet Date: Sat, 15 Apr 2023 12:38:17 +0200 Subject: [PATCH 08/17] Oops, these aren't std-only --- xtask/src/main.rs | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/xtask/src/main.rs b/xtask/src/main.rs index a50657d0a2..da61d8f14b 100644 --- a/xtask/src/main.rs +++ b/xtask/src/main.rs @@ -37,7 +37,7 @@ pub struct Target<'a> { } impl<'a> Target<'a> { - const STD_FEATURES: &str = "test-critical-section"; + const DEFAULT_FEATURES: &str = "test-critical-section"; pub const fn new(triple: &'a str, has_std: bool) -> Self { Self { triple, has_std } @@ -52,11 +52,7 @@ impl<'a> Target<'a> { } pub fn and_features(&self, features: &str) -> String { - if self.has_std { - format!("{},{}", Self::STD_FEATURES, features) - } else { - features.to_string() - } + format!("{},{}", Self::DEFAULT_FEATURES, features) } } From cefb622cf8ccfb8f50dff7ca2327d7dea5be7b7a Mon Sep 17 00:00:00 2001 From: datdenkikniet Date: Sat, 15 Apr 2023 13:17:59 +0200 Subject: [PATCH 09/17] Make all globals actually global --- xtask/src/argument_parsing.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/xtask/src/argument_parsing.rs b/xtask/src/argument_parsing.rs index e653f9a0ec..77433eef6f 100644 --- a/xtask/src/argument_parsing.rs +++ b/xtask/src/argument_parsing.rs @@ -157,7 +157,7 @@ pub enum BuildOrCheck { #[derive(Parser, Clone)] pub struct Globals { /// For which backend to build (defaults to thumbv7) - #[arg(value_enum, short, long)] + #[arg(value_enum, short, long, global = true)] pub backend: Option, /// List of comma separated examples to include, all others are excluded @@ -166,7 +166,7 @@ pub struct Globals { /// /// Example: `cargo xtask --example complex,spawn,init` /// would include complex, spawn and init - #[arg(short, long, group = "example_group")] + #[arg(short, long, group = "example_group", global = true)] pub example: Option, /// List of comma separated examples to exclude, all others are included @@ -175,11 +175,11 @@ pub struct Globals { /// /// Example: `cargo xtask --excludeexample complex,spawn,init` /// would exclude complex, spawn and init - #[arg(long, group = "example_group")] + #[arg(long, group = "example_group", global = true)] pub exampleexclude: Option, /// Enable more verbose output, repeat up to `-vvv` for even more - #[arg(short, long, action = clap::ArgAction::Count)] + #[arg(short, long, action = clap::ArgAction::Count, global = true)] pub verbose: u8, /// Enable `stderr` inheritance on child processes. @@ -187,7 +187,7 @@ pub struct Globals { /// If this flag is enabled, the output of `stderr` produced by child /// processes is printed directly to `stderr`. This will cause a lot of /// clutter, but can make debugging long-running processes a lot easier. - #[arg(short, long)] + #[arg(short, long, global = true)] pub stderr_inherited: bool, } From df69b35c250eff5858d6e994a9866be35b987a6e Mon Sep 17 00:00:00 2001 From: datdenkikniet Date: Sat, 15 Apr 2023 13:18:18 +0200 Subject: [PATCH 10/17] More housekeeping and making it work that bit better --- xtask/src/argument_parsing.rs | 22 +++- xtask/src/cargo_commands.rs | 24 ++--- xtask/src/command.rs | 190 +++++++++++++++++++++++++++++++++- xtask/src/main.rs | 9 +- 4 files changed, 223 insertions(+), 22 deletions(-) diff --git a/xtask/src/argument_parsing.rs b/xtask/src/argument_parsing.rs index 77433eef6f..3a89dfc531 100644 --- a/xtask/src/argument_parsing.rs +++ b/xtask/src/argument_parsing.rs @@ -209,7 +209,8 @@ pub enum Commands { FormatCheck(PackageOpt), /// Format code - Format(PackageOpt), + #[clap(alias = "fmt")] + Format(FormatOpt), /// Run clippy Clippy(PackageOpt), @@ -265,6 +266,15 @@ pub enum Commands { Book(Arg), } +#[derive(Args, Debug, Clone)] +pub struct FormatOpt { + #[clap(flatten)] + pub package: PackageOpt, + /// Only check formatting, without applying fixes. + #[clap(short, long, alias = "check-only")] + pub check: bool, +} + #[derive(Args, Debug, Clone)] /// Restrict to package, or run on whole workspace pub struct PackageOpt { @@ -315,3 +325,13 @@ pub enum ExtraArguments { #[command(external_subcommand)] Other(Vec), } + +impl core::fmt::Display for ExtraArguments { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + ExtraArguments::Other(args) => { + write!(f, "{}", args.join(" ")) + } + } + } +} diff --git a/xtask/src/cargo_commands.rs b/xtask/src/cargo_commands.rs index e88f31e970..26fb3148be 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, diff --git a/xtask/src/command.rs b/xtask/src/command.rs index 359a7f9fd0..99b7518557 100644 --- a/xtask/src/command.rs +++ b/xtask/src/command.rs @@ -110,9 +110,193 @@ pub enum CargoCommand<'a> { impl core::fmt::Display for CargoCommand<'_> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - let executable = self.executable(); - let args = self.args().join(" "); - write!(f, "\"{executable} {args}\"") + let p = |p: &Option| { + if let Some(package) = p { + format!("package {package}") + } else { + format!("default package") + } + }; + + let feat = |f: &Option| { + if let Some(features) = f { + format!("\"{features}\"") + } else { + format!("no features") + } + }; + + let carg = |f: &&Option<&str>| { + if let Some(cargoarg) = f { + format!("{cargoarg}") + } else { + format!("no cargo args") + } + }; + + let details = |target: &Target, + mode: &BuildMode, + features: &Option, + cargoarg: &&Option<&str>| { + let feat = feat(features); + let carg = carg(cargoarg); + if cargoarg.is_some() { + format!("({target}, {mode}, {feat}, {carg})") + } else { + format!("({target}, {mode}, {feat})") + } + }; + + match self { + CargoCommand::Run { + cargoarg, + example, + target, + features, + mode, + } => write!( + f, + "Run example {example} {}", + details(target, mode, features, cargoarg) + ), + CargoCommand::Qemu { + cargoarg, + example, + target, + features, + mode, + } => write!( + f, + "Run example {example} in QEMU {}", + details(target, mode, features, cargoarg) + ), + CargoCommand::ExampleBuild { + cargoarg, + example, + target, + features, + mode, + } => write!( + f, + "Build example {example} {}", + details(target, mode, features, cargoarg) + ), + CargoCommand::ExampleCheck { + cargoarg, + example, + target, + features, + mode, + } => write!( + f, + "Check example {example} {}", + details(target, mode, features, cargoarg) + ), + CargoCommand::Build { + cargoarg, + package, + target, + features, + mode, + } => { + let package = p(package); + write!( + f, + "Build {package} {}", + details(target, mode, features, cargoarg) + ) + } + CargoCommand::Check { + cargoarg, + package, + target, + features, + mode, + } => { + let package = p(package); + write!( + f, + "Check {package} {}", + details(target, mode, features, cargoarg) + ) + } + CargoCommand::Clippy { + cargoarg, + package, + target, + features, + } => { + let package = p(package); + let features = feat(features); + let carg = carg(cargoarg); + write!(f, "Clippy {package} ({target}, {features}, {carg})") + } + CargoCommand::Format { + cargoarg, + package, + check_only, + } => { + let package = p(package); + let carg = carg(cargoarg); + + let carg = if cargoarg.is_some() { + format!("(cargo args: {carg})") + } else { + format!("") + }; + + if *check_only { + write!(f, "Check format for {package} {carg}") + } else { + write!(f, "Format {package} {carg}") + } + } + CargoCommand::Doc { + cargoarg, + features, + arguments, + } => { + let feat = feat(features); + let carg = carg(cargoarg); + let arguments = arguments + .clone() + .map(|a| format!("{a}")) + .unwrap_or_else(|| "No extra arguments".into()); + if cargoarg.is_some() { + write!(f, "Document ({feat}, {carg}, {arguments}") + } else { + write!(f, "Document ({feat}, {arguments}") + } + } + CargoCommand::Test { + package, + features, + test, + } => { + let p = p(package); + let test = test + .clone() + .map(|t| format!("test {t}")) + .unwrap_or("all tests".into()); + let feat = feat(features); + write!(f, "Run {test} in {p} ({feat})") + } + CargoCommand::Book { arguments: _ } => write!(f, "Build the book"), + CargoCommand::ExampleSize { + cargoarg, + example, + target, + features, + mode, + arguments: _, + } => { + write!( + f, + "Compute size of example {example} {}", + details(target, mode, features, cargoarg) + ) + } + } } } diff --git a/xtask/src/main.rs b/xtask/src/main.rs index da61d8f14b..ae0f5edacd 100644 --- a/xtask/src/main.rs +++ b/xtask/src/main.rs @@ -56,6 +56,12 @@ impl<'a> Target<'a> { } } +impl core::fmt::Display for Target<'_> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "{}", self.triple) + } +} + // x86_64-unknown-linux-gnu const _X86_64: Target = Target::new("x86_64-unknown-linux-gnu", true); const ARMV6M: Target = Target::new("thumbv6m-none-eabi", false); @@ -219,8 +225,7 @@ fn main() -> anyhow::Result<()> { } Commands::Format(args) => { info!("Running cargo fmt: {args:?}"); - let check_only = false; - cargo_format(globals, &cargologlevel, &args, check_only)?; + cargo_format(globals, &cargologlevel, &args.package, args.check)?; } Commands::Clippy(args) => { info!("Running clippy on backend: {backend:?}"); From 461023e3b836db394dce0e034a1d329b1f5c8f48 Mon Sep 17 00:00:00 2001 From: datdenkikniet Date: Sat, 15 Apr 2023 13:45:58 +0200 Subject: [PATCH 11/17] More emojis and correct place for things --- xtask/src/argument_parsing.rs | 17 ++-- xtask/src/cargo_commands.rs | 179 +++++++++++----------------------- xtask/src/command.rs | 71 +++++++++++++- xtask/src/main.rs | 40 +++----- 4 files changed, 147 insertions(+), 160 deletions(-) diff --git a/xtask/src/argument_parsing.rs b/xtask/src/argument_parsing.rs index 3a89dfc531..34e0064d52 100644 --- a/xtask/src/argument_parsing.rs +++ b/xtask/src/argument_parsing.rs @@ -113,7 +113,7 @@ pub enum Backends { impl Backends { #[allow(clippy::wrong_self_convention)] - pub fn to_target(&self) -> Target { + pub fn to_target(&self) -> Target<'static> { match self { Backends::Thumbv6 => ARMV6M, Backends::Thumbv7 => ARMV7M, @@ -123,7 +123,7 @@ impl Backends { } #[allow(clippy::wrong_self_convention)] - pub fn to_rtic_feature(&self) -> &str { + pub fn to_rtic_feature(&self) -> &'static str { match self { Backends::Thumbv6 => "thumbv6-backend", Backends::Thumbv7 => "thumbv7-backend", @@ -132,14 +132,14 @@ impl Backends { } } #[allow(clippy::wrong_self_convention)] - pub fn to_rtic_macros_feature(&self) -> &str { + pub fn to_rtic_macros_feature(&self) -> &'static str { match self { Backends::Thumbv6 | Backends::Thumbv8Base => "cortex-m-source-masking", Backends::Thumbv7 | Backends::Thumbv8Main => "cortex-m-basepri", } } #[allow(clippy::wrong_self_convention)] - pub fn to_rtic_uitest_feature(&self) -> &str { + pub fn to_rtic_uitest_feature(&self) -> &'static str { match self { Backends::Thumbv6 | Backends::Thumbv8Base => "rtic-uitestv6", Backends::Thumbv7 | Backends::Thumbv8Main => "rtic-uitestv7", @@ -205,9 +205,6 @@ pub struct Cli { #[derive(Debug, Clone, Subcommand)] pub enum Commands { - /// Check formatting - FormatCheck(PackageOpt), - /// Format code #[clap(alias = "fmt")] Format(FormatOpt), @@ -270,9 +267,9 @@ pub enum Commands { pub struct FormatOpt { #[clap(flatten)] pub package: PackageOpt, - /// Only check formatting, without applying fixes. - #[clap(short, long, alias = "check-only")] - pub check: bool, + /// Apply formatting fixes immediately. + #[clap(short, long)] + pub apply: bool, } #[derive(Args, Debug, Clone)] diff --git a/xtask/src/cargo_commands.rs b/xtask/src/cargo_commands.rs index 26fb3148be..ec5fcfaa53 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())); diff --git a/xtask/src/command.rs b/xtask/src/command.rs index 99b7518557..71dda2b83b 100644 --- a/xtask/src/command.rs +++ b/xtask/src/command.rs @@ -1,4 +1,8 @@ -use crate::{debug, ExtraArguments, Package, RunResult, Target, TestRunError}; +use log::{error, info, Level}; + +use crate::{ + cargo_commands::FinalRunResult, ExtraArguments, Package, RunResult, Target, TestRunError, +}; use core::fmt; use std::{ fs::File, @@ -279,7 +283,7 @@ impl core::fmt::Display for CargoCommand<'_> { .map(|t| format!("test {t}")) .unwrap_or("all tests".into()); let feat = feat(features); - write!(f, "Run {test} in {p} ({feat})") + write!(f, "Run {test} in {p} (features: {feat})") } CargoCommand::Book { arguments: _ } => write!(f, "Build the book"), CargoCommand::ExampleSize { @@ -652,7 +656,7 @@ impl fmt::Display for BuildMode { } pub fn run_command(command: &CargoCommand, stderr_mode: OutputMode) -> anyhow::Result { - debug!("👟 {command}"); + log::info!("👟 {command}"); let result = Command::new(command.executable()) .args(command.args()) @@ -697,3 +701,64 @@ pub fn run_successful(run: &RunResult, expected_output_file: &str) -> Result<(), Ok(()) } } + +pub 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(()) + } +} diff --git a/xtask/src/main.rs b/xtask/src/main.rs index ae0f5edacd..b572591fd4 100644 --- a/xtask/src/main.rs +++ b/xtask/src/main.rs @@ -18,7 +18,7 @@ use std::{ str, }; -use log::{debug, error, info, log_enabled, trace, Level}; +use log::{error, info, log_enabled, trace, Level}; use crate::{ argument_parsing::{Backends, BuildOrCheck, Cli, Commands}, @@ -27,7 +27,7 @@ use crate::{ build_and_check_size, cargo, cargo_book, cargo_clippy, cargo_doc, cargo_example, cargo_format, cargo_test, run_test, }, - command::{run_command, run_successful, CargoCommand}, + command::{handle_results, run_command, run_successful, CargoCommand}, }; #[derive(Debug, Clone, Copy)] @@ -217,27 +217,19 @@ fn main() -> anyhow::Result<()> { Some("--quiet") }; - match cli.command { - Commands::FormatCheck(args) => { - info!("Running cargo fmt --check: {args:?}"); - let check_only = true; - cargo_format(globals, &cargologlevel, &args, check_only)?; - } - Commands::Format(args) => { - info!("Running cargo fmt: {args:?}"); - cargo_format(globals, &cargologlevel, &args.package, args.check)?; - } + let final_run_results = match &cli.command { + Commands::Format(args) => cargo_format(globals, &cargologlevel, &args.package, !args.apply), Commands::Clippy(args) => { info!("Running clippy on backend: {backend:?}"); - cargo_clippy(globals, &cargologlevel, &args, backend)?; + cargo_clippy(globals, &cargologlevel, &args, backend) } Commands::Check(args) => { info!("Checking on backend: {backend:?}"); - cargo(globals, BuildOrCheck::Check, &cargologlevel, &args, backend)?; + cargo(globals, BuildOrCheck::Check, &cargologlevel, &args, backend) } Commands::Build(args) => { info!("Building for backend: {backend:?}"); - cargo(globals, BuildOrCheck::Build, &cargologlevel, &args, backend)?; + cargo(globals, BuildOrCheck::Build, &cargologlevel, &args, backend) } Commands::ExampleCheck => { info!("Checking on backend: {backend:?}"); @@ -247,7 +239,7 @@ fn main() -> anyhow::Result<()> { &cargologlevel, backend, &examples_to_run, - )?; + ) } Commands::ExampleBuild => { info!("Building for backend: {backend:?}"); @@ -257,7 +249,7 @@ fn main() -> anyhow::Result<()> { &cargologlevel, backend, &examples_to_run, - )?; + ) } Commands::Size(args) => { // x86_64 target not valid @@ -268,7 +260,7 @@ fn main() -> anyhow::Result<()> { backend, &examples_to_run, &args.arguments, - )?; + ) } Commands::Qemu(args) | Commands::Run(args) => { // x86_64 target not valid @@ -279,23 +271,23 @@ fn main() -> anyhow::Result<()> { backend, &examples_to_run, args.overwrite_expected, - )?; + ) } Commands::Doc(args) => { info!("Running cargo doc on backend: {backend:?}"); - cargo_doc(globals, &cargologlevel, backend, &args.arguments)?; + cargo_doc(globals, &cargologlevel, backend, &args.arguments) } Commands::Test(args) => { info!("Running cargo test on backend: {backend:?}"); - cargo_test(globals, &args, backend)?; + cargo_test(globals, &args, backend) } Commands::Book(args) => { info!("Running mdbook"); - cargo_book(globals, &args.arguments)?; + cargo_book(globals, &args.arguments) } - } + }; - Ok(()) + handle_results(final_run_results) } // run example binary `example` From 622a58db5a06b1c4b29d9036ffaa593edff771b2 Mon Sep 17 00:00:00 2001 From: datdenkikniet Date: Sat, 15 Apr 2023 13:55:56 +0200 Subject: [PATCH 12/17] Also log command with enough verbosity --- xtask/src/command.rs | 19 +++++++++++++++---- xtask/src/main.rs | 2 +- 2 files changed, 16 insertions(+), 5 deletions(-) diff --git a/xtask/src/command.rs b/xtask/src/command.rs index 71dda2b83b..d05a95b35f 100644 --- a/xtask/src/command.rs +++ b/xtask/src/command.rs @@ -1,7 +1,8 @@ use log::{error, info, Level}; use crate::{ - cargo_commands::FinalRunResult, ExtraArguments, Package, RunResult, Target, TestRunError, + argument_parsing::Globals, cargo_commands::FinalRunResult, ExtraArguments, Package, RunResult, + Target, TestRunError, }; use core::fmt; use std::{ @@ -305,6 +306,12 @@ impl core::fmt::Display for CargoCommand<'_> { } impl<'a> CargoCommand<'a> { + pub fn as_cmd_string(&self) -> String { + let executable = self.executable(); + let args = self.args().join(" "); + format!("{executable} {args}") + } + fn command(&self) -> &str { match self { CargoCommand::Run { .. } | CargoCommand::Qemu { .. } => "run", @@ -702,7 +709,7 @@ pub fn run_successful(run: &RunResult, expected_output_file: &str) -> Result<(), } } -pub fn handle_results(results: Vec) -> anyhow::Result<()> { +pub fn handle_results(globals: &Globals, results: Vec) -> anyhow::Result<()> { let errors = results.iter().filter_map(|r| { if let FinalRunResult::Failed(c, r) = r { Some((c, r)) @@ -748,11 +755,15 @@ pub fn handle_results(results: Vec) -> anyhow::Result<()> { errors.clone().for_each(log_stdout_stderr(Level::Error)); successes.for_each(|(cmd, _)| { - info!("✅ Success: {cmd}"); + if globals.verbose > 0 { + info!("✅ Success: {cmd}\n {}", cmd.as_cmd_string()); + } else { + info!("✅ Success: {cmd}"); + } }); errors.clone().for_each(|(cmd, _)| { - error!("❌ Failed: {cmd}"); + error!("❌ Failed: {cmd}\n {}", cmd.as_cmd_string()); }); let ecount = errors.count(); diff --git a/xtask/src/main.rs b/xtask/src/main.rs index b572591fd4..eab21b3291 100644 --- a/xtask/src/main.rs +++ b/xtask/src/main.rs @@ -287,7 +287,7 @@ fn main() -> anyhow::Result<()> { } }; - handle_results(final_run_results) + handle_results(globals, final_run_results) } // run example binary `example` From feb00a9755ae8f96c8b761f288a6dad2eb41c5b1 Mon Sep 17 00:00:00 2001 From: datdenkikniet Date: Sat, 15 Apr 2023 14:28:24 +0200 Subject: [PATCH 13/17] Add support for "feature mixer" --- xtask/src/argument_parsing.rs | 47 +++++++++++++++-- xtask/src/cargo_commands.rs | 96 ++++++++++++++++++++++------------- 2 files changed, 104 insertions(+), 39 deletions(-) diff --git a/xtask/src/argument_parsing.rs b/xtask/src/argument_parsing.rs index 34e0064d52..70280171ef 100644 --- a/xtask/src/argument_parsing.rs +++ b/xtask/src/argument_parsing.rs @@ -46,11 +46,45 @@ impl Package { /// Without package specified the features for RTIC are required /// With only a single package which is not RTIC, no special /// features are needed - pub fn extract_features(&self, target: Target, backend: Backends) -> Option { + pub fn features( + &self, + target: Target, + backend: Backends, + partial: bool, + ) -> Vec> { match self { - Package::Rtic => Some(target.and_features(backend.to_rtic_feature())), - Package::RticMacros => Some(backend.to_rtic_macros_feature().to_owned()), - _ => None, + Package::Rtic => vec![Some(target.and_features(backend.to_rtic_feature()))], + Package::RticMacros => { + vec![Some(backend.to_rtic_macros_feature().to_string())] + } + Package::RticMonotonics => { + let features = if partial { + &["cortex-m-systick", "rp2040", "nrf52840"][..] + } else { + &[ + "cortex-m-systick", + "cortex-m-systick,systick-100hz", + "cortex-m-systick,systick-10khz", + "rp2040", + "nrf52810", + "nrf52811", + "nrf52832", + "nrf52833", + "nrf52840", + "nrf5340-app", + "nrf5340-net", + "nrf9160", + ][..] + }; + + features + .into_iter() + .map(ToString::to_string) + .map(Some) + .chain(std::iter::once(None)) + .collect() + } + _ => vec![None], } } } @@ -189,6 +223,11 @@ pub struct Globals { /// clutter, but can make debugging long-running processes a lot easier. #[arg(short, long, global = true)] pub stderr_inherited: bool, + + /// Don't build/check/test all feature combinations that are available, only + /// a necessary subset. + #[arg(long, global = true)] + pub partial: bool, } #[derive(Parser)] diff --git a/xtask/src/cargo_commands.rs b/xtask/src/cargo_commands.rs index ec5fcfaa53..9cbdaefd75 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() } From c6f4b834c184275298fabaae7b5bd70efe54b29d Mon Sep 17 00:00:00 2001 From: datdenkikniet Date: Sat, 15 Apr 2023 14:43:40 +0200 Subject: [PATCH 14/17] Fix fmt --- .github/workflows/build.yml | 4 ++-- xtask/src/argument_parsing.rs | 4 ++-- xtask/src/main.rs | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index aadb0a9756..f32e506ee0 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -31,8 +31,8 @@ jobs: - name: Cache Dependencies uses: Swatinem/rust-cache@v2 - - name: cargo xtask format-check - run: cargo xtask --verbose format-check + - name: cargo xtask fmt + run: cargo xtask --verbose fmt -c # Compilation check check: diff --git a/xtask/src/argument_parsing.rs b/xtask/src/argument_parsing.rs index 70280171ef..3ee9e34ce5 100644 --- a/xtask/src/argument_parsing.rs +++ b/xtask/src/argument_parsing.rs @@ -306,9 +306,9 @@ pub enum Commands { pub struct FormatOpt { #[clap(flatten)] pub package: PackageOpt, - /// Apply formatting fixes immediately. + /// Check-only, do not apply formatting fixes. #[clap(short, long)] - pub apply: bool, + pub check: bool, } #[derive(Args, Debug, Clone)] diff --git a/xtask/src/main.rs b/xtask/src/main.rs index eab21b3291..2bfe851f93 100644 --- a/xtask/src/main.rs +++ b/xtask/src/main.rs @@ -218,7 +218,7 @@ fn main() -> anyhow::Result<()> { }; let final_run_results = match &cli.command { - Commands::Format(args) => cargo_format(globals, &cargologlevel, &args.package, !args.apply), + Commands::Format(args) => cargo_format(globals, &cargologlevel, &args.package, args.check), Commands::Clippy(args) => { info!("Running clippy on backend: {backend:?}"); cargo_clippy(globals, &cargologlevel, &args, backend) From b11b4f8cddfb9714e542155a957e070713e297f9 Mon Sep 17 00:00:00 2001 From: datdenkikniet Date: Sat, 15 Apr 2023 15:16:43 +0200 Subject: [PATCH 15/17] Missed a paren --- xtask/src/command.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/xtask/src/command.rs b/xtask/src/command.rs index d05a95b35f..38550fe43b 100644 --- a/xtask/src/command.rs +++ b/xtask/src/command.rs @@ -266,11 +266,11 @@ impl core::fmt::Display for CargoCommand<'_> { let arguments = arguments .clone() .map(|a| format!("{a}")) - .unwrap_or_else(|| "No extra arguments".into()); + .unwrap_or_else(|| "no extra arguments".into()); if cargoarg.is_some() { - write!(f, "Document ({feat}, {carg}, {arguments}") + write!(f, "Document ({feat}, {carg}, {arguments})") } else { - write!(f, "Document ({feat}, {arguments}") + write!(f, "Document ({feat}, {arguments})") } } CargoCommand::Test { From 51284efd0eadbc37a5c79afdeff17df84a928370 Mon Sep 17 00:00:00 2001 From: datdenkikniet Date: Sat, 15 Apr 2023 15:24:41 +0200 Subject: [PATCH 16/17] Add more default members --- .github/workflows/build.yml | 2 +- Cargo.toml | 5 +++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index f32e506ee0..f2bec7dce4 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -251,7 +251,7 @@ jobs: tool: lychee - name: Remove cargo-config - run: rm -f .cargo/config + run: rm -f .cargo/config.toml - name: Build docs # TODO: Any difference between backends? diff --git a/Cargo.toml b/Cargo.toml index 98ecfea66e..6fccc1da54 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,11 @@ [workspace] default-members = [ "rtic", + "rtic-sync", + "rtic-common", + "rtic-macros", + "rtic-monotonics", + "rtic-time", ] members = [ "rtic", From aeeb623a70b2bf4ae78f1629a5171406ba51ec4d Mon Sep 17 00:00:00 2001 From: datdenkikniet Date: Sat, 15 Apr 2023 15:32:33 +0200 Subject: [PATCH 17/17] Don't print no cargo args here either --- xtask/src/command.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/xtask/src/command.rs b/xtask/src/command.rs index 38550fe43b..b62724ab73 100644 --- a/xtask/src/command.rs +++ b/xtask/src/command.rs @@ -234,7 +234,11 @@ impl core::fmt::Display for CargoCommand<'_> { let package = p(package); let features = feat(features); let carg = carg(cargoarg); - write!(f, "Clippy {package} ({target}, {features}, {carg})") + if cargoarg.is_some() { + write!(f, "Clippy {package} ({target}, {features}, {carg})") + } else { + write!(f, "Clippy {package} ({target}, {features})") + } } CargoCommand::Format { cargoarg,