mirror of
https://github.com/rtic-rs/rtic.git
synced 2024-11-29 06:54:33 +01:00
xtask: forward globals through the chain and add stderr-inheritance flag
This commit is contained in:
parent
fa92d8abe7
commit
18522122f1
4 changed files with 103 additions and 39 deletions
|
@ -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<Backends>,
|
||||
|
@ -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<Package>,
|
||||
}
|
||||
|
||||
#[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)]
|
||||
|
|
|
@ -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<ExtraArguments>,
|
||||
|
@ -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<ExtraArguments>) -> anyhow::Result<()> {
|
||||
pub fn cargo_book(globals: &Globals, arguments: &Option<ExtraArguments>) -> anyhow::Result<()> {
|
||||
command_parser(
|
||||
globals,
|
||||
&CargoCommand::Book {
|
||||
arguments: arguments.clone(),
|
||||
},
|
||||
|
@ -183,6 +198,7 @@ pub fn cargo_book(arguments: &Option<ExtraArguments>) -> 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}");
|
||||
}
|
||||
});
|
||||
|
|
|
@ -13,6 +13,21 @@ pub enum BuildMode {
|
|||
Debug,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq)]
|
||||
pub enum OutputMode {
|
||||
PipedAndCollected,
|
||||
Inherited,
|
||||
}
|
||||
|
||||
impl From<OutputMode> 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<RunResult> {
|
||||
pub fn run_command(command: &CargoCommand, stderr_mode: OutputMode) -> anyhow::Result<RunResult> {
|
||||
let command_display = command.executable();
|
||||
let args = command.args();
|
||||
|
||||
|
@ -425,7 +440,7 @@ pub fn run_command(command: &CargoCommand) -> anyhow::Result<RunResult> {
|
|||
let result = Command::new(command.executable())
|
||||
.args(command.args())
|
||||
.stdout(Stdio::piped())
|
||||
.stderr(Stdio::piped())
|
||||
.stderr(stderr_mode)
|
||||
.output()?;
|
||||
|
||||
let exit_status = result.status;
|
||||
|
|
|
@ -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 {
|
||||
|
|
Loading…
Reference in a new issue