xtask: Major overhaul

Fix error printouts for examples,
Rename BuildAll -> Build
Rename Build -> ExampleBuild

Command interface changed, targets by defalt only v6 and v7
This commit is contained in:
Henrik Tjäder 2023-02-06 13:21:04 +01:00
parent d5471f2da4
commit 806b3668e8
2 changed files with 432 additions and 173 deletions

View file

@ -1,11 +1,7 @@
use crate::{debug, RunResult, Sizearguments, TestRunError}; use crate::{debug, info, RunResult, Sizearguments, TestRunError};
use core::fmt; use core::fmt;
use os_pipe::pipe; use os_pipe::pipe;
use std::{ use std::{fs::File, io::Read, process::Command};
fs::File,
io::Read,
process::{Command, Stdio},
};
#[allow(dead_code)] #[allow(dead_code)]
#[derive(Debug, Clone, Copy, PartialEq)] #[derive(Debug, Clone, Copy, PartialEq)]
@ -16,6 +12,8 @@ pub enum BuildMode {
#[derive(Debug)] #[derive(Debug)]
pub enum CargoCommand<'a> { pub enum CargoCommand<'a> {
// For future embedded-ci
#[allow(dead_code)]
Run { Run {
cargoarg: &'a Option<&'a str>, cargoarg: &'a Option<&'a str>,
example: &'a str, example: &'a str,
@ -23,25 +21,47 @@ pub enum CargoCommand<'a> {
features: Option<&'a str>, features: Option<&'a str>,
mode: BuildMode, mode: BuildMode,
}, },
Qemu {
cargoarg: &'a Option<&'a str>,
example: &'a str,
target: &'a str,
features: Option<&'a str>,
mode: BuildMode,
},
ExampleBuild {
cargoarg: &'a Option<&'a str>,
example: &'a str,
target: &'a str,
features: Option<&'a str>,
mode: BuildMode,
},
ExampleCheck {
cargoarg: &'a Option<&'a str>,
example: &'a str,
target: &'a str,
features: Option<&'a str>,
mode: BuildMode,
},
Build { Build {
cargoarg: &'a Option<&'a str>, cargoarg: &'a Option<&'a str>,
example: &'a str, package: Vec<String>,
target: &'a str, target: &'a str,
features: Option<&'a str>, features: Option<&'a str>,
mode: BuildMode, mode: BuildMode,
}, },
BuildAll { Check {
cargoarg: &'a Option<&'a str>,
target: &'a str,
features: Option<&'a str>,
mode: BuildMode,
},
CheckAll {
cargoarg: &'a Option<&'a str>, cargoarg: &'a Option<&'a str>,
package: Vec<String>,
target: &'a str, target: &'a str,
features: Option<&'a str>, features: Option<&'a str>,
}, },
Size { Clippy {
cargoarg: &'a Option<&'a str>,
package: Vec<String>,
target: &'a str,
features: Option<&'a str>,
},
ExampleSize {
cargoarg: &'a Option<&'a str>, cargoarg: &'a Option<&'a str>,
example: &'a str, example: &'a str,
target: &'a str, target: &'a str,
@ -54,16 +74,21 @@ pub enum CargoCommand<'a> {
impl<'a> CargoCommand<'a> { impl<'a> CargoCommand<'a> {
fn name(&self) -> &str { fn name(&self) -> &str {
match self { match self {
CargoCommand::Run { .. } => "run", CargoCommand::Run { .. } | CargoCommand::Qemu { .. } => "run",
CargoCommand::Build { .. } => "build", CargoCommand::ExampleCheck { .. } | CargoCommand::Check { .. } => "check",
CargoCommand::Size { .. } => "size", CargoCommand::ExampleBuild { .. } | CargoCommand::Build { .. } => "build",
CargoCommand::BuildAll { .. } => "build", CargoCommand::ExampleSize { .. } => "size",
CargoCommand::CheckAll { .. } => "check", CargoCommand::Clippy { .. } => "clippy",
// TODO
// CargoCommand::Fmt { .. } => "fmt",
// CargoCommand::Test { .. } => "test",
// CargoCommand::Doc { .. } => "doc",
} }
} }
pub fn args(&self) -> Vec<&str> { pub fn args(&self) -> Vec<&str> {
match self { match self {
// For future embedded-ci, for now the same as Qemu
CargoCommand::Run { CargoCommand::Run {
cargoarg, cargoarg,
example, example,
@ -85,43 +110,7 @@ impl<'a> CargoCommand<'a> {
} }
args args
} }
CargoCommand::BuildAll { CargoCommand::Qemu {
cargoarg,
target,
features,
mode,
} => {
let mut args = vec!["+nightly"];
if let Some(cargoarg) = cargoarg {
args.extend_from_slice(&[cargoarg]);
}
args.extend_from_slice(&[self.name(), "--examples", "--target", target]);
if let Some(feature) = features {
args.extend_from_slice(&["--features", feature]);
}
if let Some(flag) = mode.to_flag() {
args.push(flag);
}
args
}
CargoCommand::CheckAll {
cargoarg,
target,
features,
} => {
let mut args = vec!["+nightly"];
if let Some(cargoarg) = cargoarg {
args.extend_from_slice(&[cargoarg]);
}
args.extend_from_slice(&[self.name(), "--examples", "--target", target]);
if let Some(feature) = features {
args.extend_from_slice(&["--features", feature]);
}
args
}
CargoCommand::Build {
cargoarg, cargoarg,
example, example,
target, target,
@ -142,7 +131,121 @@ impl<'a> CargoCommand<'a> {
} }
args args
} }
CargoCommand::Size { CargoCommand::Build {
cargoarg,
package,
target,
features,
mode,
} => {
let mut args = vec!["+nightly"];
if let Some(cargoarg) = cargoarg {
args.extend_from_slice(&[cargoarg]);
}
args.extend_from_slice(&[self.name(), "--target", target]);
if !package.is_empty() {
for package in package {
args.extend_from_slice(&["--package", package]);
}
}
if let Some(feature) = features {
args.extend_from_slice(&["--features", feature]);
}
if let Some(flag) = mode.to_flag() {
args.push(flag);
}
args
}
CargoCommand::Check {
cargoarg,
package,
target,
features,
} => {
let mut args = vec!["+nightly"];
if let Some(cargoarg) = cargoarg {
args.extend_from_slice(&[cargoarg]);
}
args.extend_from_slice(&[self.name(), "--target", target]);
if !package.is_empty() {
for package in package {
args.extend_from_slice(&["--package", package]);
}
}
if let Some(feature) = features {
args.extend_from_slice(&["--features", feature]);
}
args
}
CargoCommand::Clippy {
cargoarg,
package,
target,
features,
} => {
let mut args = vec!["+nightly"];
if let Some(cargoarg) = cargoarg {
args.extend_from_slice(&[cargoarg]);
}
args.extend_from_slice(&[self.name(), "--target", target]);
if !package.is_empty() {
for package in package {
args.extend_from_slice(&["--package", package]);
}
}
if let Some(feature) = features {
args.extend_from_slice(&["--features", feature]);
}
args
}
CargoCommand::ExampleBuild {
cargoarg,
example,
target,
features,
mode,
} => {
let mut args = vec!["+nightly"];
if let Some(cargoarg) = cargoarg {
args.extend_from_slice(&[cargoarg]);
}
args.extend_from_slice(&[self.name(), "--example", example, "--target", target]);
if let Some(feature) = features {
args.extend_from_slice(&["--features", feature]);
}
if let Some(flag) = mode.to_flag() {
args.push(flag);
}
args
}
CargoCommand::ExampleCheck {
cargoarg,
example,
target,
features,
mode,
} => {
let mut args = vec!["+nightly"];
if let Some(cargoarg) = cargoarg {
args.extend_from_slice(&[cargoarg]);
}
args.extend_from_slice(&[self.name(), "--example", example, "--target", target]);
if let Some(feature) = features {
args.extend_from_slice(&["--features", feature]);
}
if let Some(flag) = mode.to_flag() {
args.push(flag);
}
args
}
CargoCommand::ExampleSize {
cargoarg, cargoarg,
example, example,
target, target,
@ -202,13 +305,13 @@ impl fmt::Display for BuildMode {
pub fn run_command(command: &CargoCommand) -> anyhow::Result<RunResult> { pub fn run_command(command: &CargoCommand) -> anyhow::Result<RunResult> {
let (mut reader, writer) = pipe()?; let (mut reader, writer) = pipe()?;
let (mut error_reader, error_writer) = pipe()?;
debug!("👟 {} {}", command.command(), command.args().join(" ")); debug!("👟 {} {}", command.command(), command.args().join(" "));
let mut handle = Command::new(command.command()) let mut handle = Command::new(command.command())
.args(command.args()) .args(command.args())
.stdout(writer) .stdout(writer)
// Throw away stderr, TODO .stderr(error_writer)
.stderr(Stdio::null())
.spawn()?; .spawn()?;
// retrieve output and clean up // retrieve output and clean up
@ -216,6 +319,12 @@ pub fn run_command(command: &CargoCommand) -> anyhow::Result<RunResult> {
reader.read_to_string(&mut output)?; reader.read_to_string(&mut output)?;
let exit_status = handle.wait()?; let exit_status = handle.wait()?;
let mut error_output = String::new();
error_reader.read_to_string(&mut error_output)?;
if !error_output.is_empty() {
info!("{error_output}");
}
Ok(RunResult { Ok(RunResult {
exit_status, exit_status,
output, output,

View file

@ -2,7 +2,7 @@ mod build;
mod command; mod command;
use anyhow::bail; use anyhow::bail;
use clap::{Parser, Subcommand}; use clap::{Args, Parser, Subcommand};
use core::fmt; use core::fmt;
use rayon::prelude::*; use rayon::prelude::*;
use std::{ use std::{
@ -24,6 +24,8 @@ use crate::{
command::{run_command, run_successful, BuildMode, CargoCommand}, command::{run_command, run_successful, BuildMode, CargoCommand},
}; };
// x86_64-unknown-linux-gnu
const _X86_64: &str = "x86_64-unknown-linux-gnu";
const ARMV6M: &str = "thumbv6m-none-eabi"; const ARMV6M: &str = "thumbv6m-none-eabi";
const ARMV7M: &str = "thumbv7m-none-eabi"; const ARMV7M: &str = "thumbv7m-none-eabi";
const ARMV8MBASE: &str = "thumbv8m.base-none-eabi"; const ARMV8MBASE: &str = "thumbv8m.base-none-eabi";
@ -35,10 +37,14 @@ const DEFAULT_FEATURES: Option<&str> = Some("test-critical-section");
#[command(author, version, about, long_about = None)] #[command(author, version, about, long_about = None)]
/// RTIC xtask powered testing toolbox /// RTIC xtask powered testing toolbox
struct Cli { struct Cli {
/// For which ARM target to build: v7 or v6 /// For which target to build
/// ///
/// Defaults to all targets if omitted. /// Defaults to these targets if omitted:
/// The permissible targets are: ///
/// thumbv6m-none-eabi
/// thumbv7m-none-eabi
///
/// The valid targets are:
/// ///
/// thumbv6m-none-eabi /// thumbv6m-none-eabi
/// thumbv7m-none-eabi /// thumbv7m-none-eabi
@ -47,9 +53,9 @@ struct Cli {
#[arg(short, long)] #[arg(short, long)]
target: Option<String>, target: Option<String>,
/// List of comma separated examples to run, all others are excluded /// List of comma separated examples to include, all others are excluded
/// ///
/// If omitted all examples are run /// If omitted all examples are included
/// ///
/// Example: `cargo xtask --example complex,spawn,init` /// Example: `cargo xtask --example complex,spawn,init`
/// would include complex, spawn and init /// would include complex, spawn and init
@ -58,7 +64,7 @@ struct Cli {
/// List of comma separated examples to exclude, all others are included /// List of comma separated examples to exclude, all others are included
/// ///
/// If omitted all examples are run /// If omitted all examples are included
/// ///
/// Example: `cargo xtask --excludeexample complex,spawn,init` /// Example: `cargo xtask --excludeexample complex,spawn,init`
/// would exclude complex, spawn and init /// would exclude complex, spawn and init
@ -69,11 +75,9 @@ struct Cli {
#[arg(short, long, action = clap::ArgAction::Count)] #[arg(short, long, action = clap::ArgAction::Count)]
verbose: u8, verbose: u8,
/// Subcommand picking which kind of operation /// Subcommand selecting operation
///
/// If omitted run all tests
#[command(subcommand)] #[command(subcommand)]
command: Option<Commands>, command: Commands,
} }
#[derive(Debug, Subcommand)] #[derive(Debug, Subcommand)]
@ -89,17 +93,51 @@ enum Commands {
/// Run examples in QEMU and compare against expected output /// Run examples in QEMU and compare against expected output
/// ///
/// Example runtime output is matched against `rtic/ci/expected/` /// Example runtime output is matched against `rtic/ci/expected/`
Qemu { ///
/// If expected output is missing or mismatching, recreate the file /// Requires that an ARM target is selected
/// Qemu(QemuAndRun),
/// This overwrites only missing or mismatching
#[arg(long)] /// Run examples through embedded-ci and compare against expected output
overwrite_expected: bool, ///
}, /// unimplemented!() For now TODO, equal to Qemu
///
/// Example runtime output is matched against `rtic/ci/expected/`
///
/// Requires that an ARM target is selected
Run(QemuAndRun),
/// Build all examples /// Build all examples
Build, ExampleBuild,
/// Check all examples
Check, /// Check all packages
ExampleCheck,
/// Build all examples
Build(Package),
/// Check all packages
Check(Package),
/// Run clippy
Clippy(Package),
}
#[derive(Args, Debug)]
/// Restrict to package, or run on whole workspace
struct Package {
/// For which package/workspace member to operate
///
/// If omitted, work on all
package: Option<String>,
}
#[derive(Args, Debug)]
struct QemuAndRun {
/// If expected output is missing or mismatching, recreate the file
///
/// This overwrites only missing or mismatching
#[arg(long)]
overwrite_expected: bool,
} }
#[derive(Debug, Parser)] #[derive(Debug, Parser)]
@ -174,16 +212,8 @@ fn main() -> anyhow::Result<()> {
if !probably_running_from_repo_root { if !probably_running_from_repo_root {
bail!("xtasks can only be executed from the root of the `rtic` repository"); bail!("xtasks can only be executed from the root of the `rtic` repository");
} }
for entry in std::fs::read_dir(".").unwrap() {
let mut targets: Vec<String> = [ARMV7M.to_owned(), ARMV6M.to_owned()].to_vec();
let mut targets: Vec<String> = [
ARMV7M.to_owned(),
ARMV6M.to_owned(),
ARMV8MBASE.to_owned(),
ARMV8MMAIN.to_owned(),
]
.to_vec();
let examples: Vec<_> = std::fs::read_dir("./rtic/examples")? let examples: Vec<_> = std::fs::read_dir("./rtic/examples")?
.filter_map(|p| p.ok()) .filter_map(|p| p.ok())
@ -206,27 +236,14 @@ fn main() -> anyhow::Result<()> {
.init(); .init();
trace!("default logging level: {0}", cli.verbose); trace!("default logging level: {0}", cli.verbose);
trace!("examples: {examples:?}");
let target = cli.target; let target = cli.target;
let example = cli.example;
if let Some(example) = example {
if examples.contains(&example) {
info!("Testing example: {example}");
// If we managed to filter, set the examples to test to only this one
examples = vec![example]
} else {
error!(
"\nThe example you specified is not available. Available examples are:\
\n{examples:#?}\n\
By default if example flag is emitted, all examples are tested.",
);
process::exit(1);
}
}
if let Some(target) = target { if let Some(target) = target {
if targets.contains(&target) { let mut targets_extended = targets.clone();
targets_extended.push(ARMV8MBASE.to_owned());
targets_extended.push(ARMV8MMAIN.to_owned());
if targets_extended.contains(&target) {
debug!("\nTesting target: {target}"); debug!("\nTesting target: {target}");
// If we managed to filter, set the targets to test to only this one // If we managed to filter, set the targets to test to only this one
targets = vec![target] targets = vec![target]
@ -240,66 +257,129 @@ fn main() -> anyhow::Result<()> {
} }
} }
let example = cli.example;
let exampleexclude = cli.exampleexclude;
let examples_to_run = {
let mut examples_to_run = examples.clone();
if let Some(example) = example {
examples_to_run = examples.clone();
let examples_to_exclude = example.split(',').collect::<Vec<&str>>();
// From the list of all examples, remove all not listed as included
for ex in examples_to_exclude {
examples_to_run.retain(|x| *x.as_str() == *ex);
}
};
if let Some(example) = exampleexclude {
examples_to_run = examples.clone();
let examples_to_exclude = example.split(',').collect::<Vec<&str>>();
// From the list of all examples, remove all those listed as excluded
for ex in examples_to_exclude {
examples_to_run.retain(|x| *x.as_str() != *ex);
}
};
if log_enabled!(Level::Trace) {
trace!("All examples:\n{examples:?} number: {}", examples.len());
trace!(
"examples_to_run:\n{examples_to_run:?} number: {}",
examples_to_run.len()
);
}
if examples_to_run.is_empty() {
error!(
"\nThe example(s) you specified is not available. Available examples are:\
\n{examples:#?}\n\
By default if example flag is emitted, all examples are tested.",
);
process::exit(1);
} else {
}
examples_to_run
};
init_build_dir()?; init_build_dir()?;
#[allow(clippy::if_same_then_else)] #[allow(clippy::if_same_then_else)]
let cargoarg = if log_enabled!(Level::Trace) { let cargoarg = if log_enabled!(Level::Trace) {
Some("-vv")
} else if log_enabled!(Level::Debug) {
Some("-v") Some("-v")
} else if log_enabled!(Level::Debug) {
None
} else if log_enabled!(Level::Info) { } else if log_enabled!(Level::Info) {
None None
} else if log_enabled!(Level::Warn) || log_enabled!(Level::Error) { } else if log_enabled!(Level::Warn) || log_enabled!(Level::Error) {
Some("--quiet") None
} else { } else {
// Off case // Off case
Some("--quiet") Some("--quiet")
}; };
match cli.command { match cli.command {
Some(Commands::Size(arguments)) => { Commands::Size(arguments) => {
debug!("Measuring on target(s): {targets:?}"); debug!("Measuring on target(s): {targets:?}");
// x86_64 target not valid
for t in &targets { for t in &targets {
info!("Measuring for target: {t:?}"); info!("Measuring for target: {t:?}");
build_and_check_size(&cargoarg, t, &examples, &arguments.sizearguments)?; build_and_check_size(&cargoarg, t, &examples_to_run, &arguments.sizearguments)?;
} }
} }
Some(Commands::Qemu { Commands::Qemu(args) | Commands::Run(args) => {
overwrite_expected: overwrite, debug!("Running on target(s): {targets:?}");
}) => { // x86_64 target not valid
debug!("Testing on target(s): {targets:?}");
for t in &targets { for t in &targets {
info!("Testing for target: {t:?}"); info!("Testing for target: {t:?}");
run_test(&cargoarg, t, &examples, overwrite)?; run_test(&cargoarg, t, &examples_to_run, args.overwrite_expected)?;
} }
} }
Some(Commands::Build) => { Commands::ExampleBuild => {
debug!("Building for target(s): {targets:?}"); debug!("Building for target(s): {targets:?}");
for t in &targets { for t in &targets {
info!("Building for target: {t:?}"); info!("Building for target: {t:?}");
build_all(&cargoarg, t)?; example_build(&cargoarg, t, &examples_to_run)?;
} }
} }
Some(Commands::Check) => { Commands::ExampleCheck => {
debug!("Checking on target(s): {targets:?}"); debug!("Checking on target(s): {targets:?}");
for t in &targets { for t in &targets {
info!("Checking on target: {t:?}"); info!("Checking on target: {t:?}");
check_all(&cargoarg, t)?; example_check(&cargoarg, t, &examples_to_run)?;
} }
} }
None => { Commands::Build(args) => {
todo!(); debug!("Building for target(s): {targets:?}");
for t in &targets {
info!("Building for target: {t:?}");
cargo_build(&cargoarg, &args, t)?;
}
}
Commands::Check(args) => {
debug!("Checking on target(s): {targets:?}");
for t in &targets {
info!("Checking on target: {t:?}");
cargo_check(&cargoarg, &args, t)?;
}
}
Commands::Clippy(args) => {
debug!("Clippy on target(s): {targets:?}");
for t in &targets {
info!("Running clippy on target: {t:?}");
cargo_clippy(&cargoarg, &args, t)?;
}
} }
} }
Ok(()) Ok(())
} }
fn build_all(cargoarg: &Option<&str>, target: &str) -> anyhow::Result<()> { fn cargo_build(cargoarg: &Option<&str>, package: &Package, target: &str) -> anyhow::Result<()> {
arm_example( command_parser(
&CargoCommand::BuildAll { &CargoCommand::Build {
cargoarg, cargoarg,
package: package_filter(package),
target, target,
features: DEFAULT_FEATURES, features: None,
mode: BuildMode::Release, mode: BuildMode::Release,
}, },
false, false,
@ -307,12 +387,26 @@ fn build_all(cargoarg: &Option<&str>, target: &str) -> anyhow::Result<()> {
Ok(()) Ok(())
} }
fn check_all(cargoarg: &Option<&str>, target: &str) -> anyhow::Result<()> { fn cargo_check(cargoarg: &Option<&str>, package: &Package, target: &str) -> anyhow::Result<()> {
arm_example( command_parser(
&CargoCommand::CheckAll { &CargoCommand::Check {
cargoarg, cargoarg,
package: package_filter(package),
target, target,
features: DEFAULT_FEATURES, features: None,
},
false,
)?;
Ok(())
}
fn cargo_clippy(cargoarg: &Option<&str>, package: &Package, target: &str) -> anyhow::Result<()> {
command_parser(
&CargoCommand::Clippy {
cargoarg,
package: package_filter(package),
target,
features: None,
}, },
false, false,
)?; )?;
@ -326,16 +420,18 @@ fn run_test(
overwrite: bool, overwrite: bool,
) -> anyhow::Result<()> { ) -> anyhow::Result<()> {
examples.into_par_iter().for_each(|example| { examples.into_par_iter().for_each(|example| {
let cmd = CargoCommand::Build { let cmd = CargoCommand::ExampleBuild {
cargoarg: &Some("--quiet"), cargoarg: &Some("--quiet"),
example, example,
target, target,
features: DEFAULT_FEATURES, features: DEFAULT_FEATURES,
mode: BuildMode::Release, mode: BuildMode::Release,
}; };
arm_example(&cmd, false).unwrap(); if let Err(err) = command_parser(&cmd, false) {
error!("{err}");
}
let cmd = CargoCommand::Run { let cmd = CargoCommand::Qemu {
cargoarg, cargoarg,
example, example,
target, target,
@ -343,7 +439,44 @@ fn run_test(
mode: BuildMode::Release, mode: BuildMode::Release,
}; };
arm_example(&cmd, overwrite).unwrap(); if let Err(err) = command_parser(&cmd, overwrite) {
error!("{err}");
}
});
Ok(())
}
fn example_check(cargoarg: &Option<&str>, target: &str, examples: &[String]) -> anyhow::Result<()> {
examples.into_par_iter().for_each(|example| {
let cmd = CargoCommand::ExampleCheck {
cargoarg,
example,
target,
features: DEFAULT_FEATURES,
mode: BuildMode::Release,
};
if let Err(err) = command_parser(&cmd, overwrite) {
error!("{err}");
}
});
Ok(())
}
fn example_build(cargoarg: &Option<&str>, target: &str, examples: &[String]) -> anyhow::Result<()> {
examples.into_par_iter().for_each(|example| {
let cmd = CargoCommand::ExampleBuild {
cargoarg,
example,
target,
features: DEFAULT_FEATURES,
mode: BuildMode::Release,
};
if let Err(err) = command_parser(&cmd, overwrite) {
error!("{err}");
}
}); });
Ok(()) Ok(())
@ -357,16 +490,18 @@ fn build_and_check_size(
) -> anyhow::Result<()> { ) -> anyhow::Result<()> {
examples.into_par_iter().for_each(|example| { examples.into_par_iter().for_each(|example| {
// Make sure the requested example(s) are built // Make sure the requested example(s) are built
let cmd = CargoCommand::Build { let cmd = CargoCommand::ExampleBuild {
cargoarg: &Some("--quiet"), cargoarg: &Some("--quiet"),
example, example,
target, target,
features: DEFAULT_FEATURES, features: DEFAULT_FEATURES,
mode: BuildMode::Release, mode: BuildMode::Release,
}; };
arm_example(&cmd, false).unwrap(); if let Err(err) = command_parser(&cmd, false) {
error!("{err}");
}
let cmd = CargoCommand::Size { let cmd = CargoCommand::ExampleSize {
cargoarg, cargoarg,
example, example,
target, target,
@ -374,16 +509,52 @@ fn build_and_check_size(
mode: BuildMode::Release, mode: BuildMode::Release,
arguments: size_arguments.clone(), arguments: size_arguments.clone(),
}; };
arm_example(&cmd, false).unwrap(); if let Err(err) = command_parser(&cmd, false) {
error!("{err}");
}
}); });
Ok(()) Ok(())
} }
fn package_filter(package: &Package) -> Vec<String> {
// TODO Parse Cargo.toml workspace definition instead?
let packages: Vec<String> = [
"rtic".to_owned(),
"rtic-macros".to_owned(),
"rtic-channel".to_owned(),
"rtic-common".to_owned(),
"rtic-macros".to_owned(),
"rtic-monotonics".to_owned(),
"rtic-time".to_owned(),
]
.to_vec();
let package_selected;
if let Some(package) = package.package.clone() {
if packages.contains(&package) {
debug!("\nTesting package: {package}");
// If we managed to filter, set the packages to test to only this one
package_selected = vec![package]
} else {
error!(
"\nThe package you specified is not available. Available packages are:\
\n{packages:#?}\n\
By default all packages are tested.",
);
process::exit(1);
}
} else {
package_selected = packages;
}
package_selected
}
// run example binary `example` // run example binary `example`
fn arm_example(command: &CargoCommand, overwrite: bool) -> anyhow::Result<()> { fn command_parser(command: &CargoCommand, overwrite: bool) -> anyhow::Result<()> {
match *command { match *command {
CargoCommand::Run { example, .. } => { CargoCommand::Qemu { example, .. } | CargoCommand::Run { example, .. } => {
let run_file = format!("{example}.run"); let run_file = format!("{example}.run");
let expected_output_file = ["rtic", "ci", "expected", &run_file] let expected_output_file = ["rtic", "ci", "expected", &run_file]
.iter() .iter()
@ -393,6 +564,7 @@ fn arm_example(command: &CargoCommand, overwrite: bool) -> anyhow::Result<()> {
.map_err(TestRunError::PathConversionError)?; .map_err(TestRunError::PathConversionError)?;
// cargo run <..> // cargo run <..>
info!("Running example: {example}");
let cargo_run_result = run_command(command)?; let cargo_run_result = run_command(command)?;
info!("{}", cargo_run_result.output); info!("{}", cargo_run_result.output);
@ -416,40 +588,18 @@ fn arm_example(command: &CargoCommand, overwrite: bool) -> anyhow::Result<()> {
} }
Ok(()) Ok(())
} }
CargoCommand::Build { .. } => { CargoCommand::ExampleBuild { .. }
// cargo run <..> | CargoCommand::ExampleCheck { .. }
let cargo_build_result = run_command(command)?; | CargoCommand::Build { .. }
if !cargo_build_result.output.is_empty() { | CargoCommand::Check { .. }
info!("{}", cargo_build_result.output); | CargoCommand::Clippy { .. }
| CargoCommand::ExampleSize { .. } => {
let cargo_result = run_command(command)?;
if !cargo_result.output.is_empty() {
info!("{}", cargo_result.output);
} }
Ok(()) Ok(())
} }
CargoCommand::BuildAll { .. } => {
// cargo build --examples
let cargo_build_result = run_command(command)?;
if !cargo_build_result.output.is_empty() {
info!("{}", cargo_build_result.output);
}
Ok(())
}
CargoCommand::CheckAll { .. } => {
// cargo check --examples
let cargo_check_result = run_command(command)?;
if !cargo_check_result.output.is_empty() {
info!("{}", cargo_check_result.output);
}
Ok(())
}
CargoCommand::Size { .. } => {
// cargo size
let cargo_size_result = run_command(command)?;
if !cargo_size_result.output.is_empty() {
info!("{}", cargo_size_result.output);
}
Ok(())
}
} }
} }