diff --git a/xtask/src/cargo_commands.rs b/xtask/src/cargo_commands.rs new file mode 100644 index 0000000000..996fa9c918 --- /dev/null +++ b/xtask/src/cargo_commands.rs @@ -0,0 +1,267 @@ +use crate::{ + argument_parsing::{Backends, BuildOrCheck, Package, PackageOpt, Sizearguments, TestMetadata}, + command::{BuildMode, CargoCommand}, + command_parser, package_feature_extractor, DEFAULT_FEATURES, +}; +use log::error; +use rayon::prelude::*; + +/// Cargo command to either build or check +pub fn cargo( + operation: BuildOrCheck, + cargoarg: &Option<&str>, + package: &PackageOpt, + backend: Backends, +) -> anyhow::Result<()> { + let features = package_feature_extractor(package, backend); + + let command = match operation { + BuildOrCheck::Check => CargoCommand::Check { + cargoarg, + package: package.package, + target: backend.to_target(), + features, + mode: BuildMode::Release, + }, + BuildOrCheck::Build => CargoCommand::Build { + cargoarg, + package: package.package, + target: backend.to_target(), + features, + mode: BuildMode::Release, + }, + }; + command_parser(&command, false)?; + Ok(()) +} + +/// Cargo command to either build or check all examples +/// +/// The examples are in rtic/examples +pub fn cargo_example( + operation: BuildOrCheck, + cargoarg: &Option<&str>, + backend: Backends, + examples: &[String], +) -> anyhow::Result<()> { + examples.into_par_iter().for_each(|example| { + let features = Some(format!( + "{},{}", + DEFAULT_FEATURES, + backend.to_rtic_feature() + )); + + let command = match operation { + BuildOrCheck::Check => CargoCommand::ExampleCheck { + cargoarg, + example, + target: backend.to_target(), + features, + mode: BuildMode::Release, + }, + BuildOrCheck::Build => CargoCommand::ExampleBuild { + cargoarg, + example, + target: backend.to_target(), + features, + mode: BuildMode::Release, + }, + }; + + if let Err(err) = command_parser(&command, false) { + error!("{err}"); + } + }); + + Ok(()) +} + +/// Run cargo clippy on selected package +pub fn cargo_clippy( + cargoarg: &Option<&str>, + package: &PackageOpt, + backend: Backends, +) -> anyhow::Result<()> { + let features = package_feature_extractor(package, backend); + command_parser( + &CargoCommand::Clippy { + cargoarg, + package: package.package, + target: backend.to_target(), + features, + }, + false, + )?; + Ok(()) +} + +/// Run cargo fmt on selected package +pub fn cargo_format( + cargoarg: &Option<&str>, + package: &PackageOpt, + check_only: bool, +) -> anyhow::Result<()> { + command_parser( + &CargoCommand::Format { + cargoarg, + package: package.package, + check_only, + }, + false, + )?; + Ok(()) +} + +/// Run cargo doc +pub fn cargo_doc(cargoarg: &Option<&str>, backend: Backends) -> anyhow::Result<()> { + let features = Some(format!( + "{},{}", + DEFAULT_FEATURES, + backend.to_rtic_feature() + )); + + command_parser(&CargoCommand::Doc { cargoarg, features }, false)?; + Ok(()) +} + +/// 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<()> { + if let Some(package) = package.package { + let cmd = match package { + Package::Rtic => TestMetadata::match_package(package, backend), + Package::RticArbiter => TestMetadata::match_package(package, backend), + Package::RticChannel => TestMetadata::match_package(package, backend), + Package::RticCommon => TestMetadata::match_package(package, backend), + Package::RticMacros => TestMetadata::match_package(package, backend), + Package::RticMonotonics => TestMetadata::match_package(package, backend), + Package::RticTime => TestMetadata::match_package(package, backend), + }; + command_parser(&cmd, false)?; + } else { + // Iterate over all workspace packages + for package in [ + Package::Rtic, + Package::RticArbiter, + Package::RticChannel, + Package::RticCommon, + Package::RticMacros, + Package::RticMonotonics, + Package::RticTime, + ] { + let mut error_messages = vec![]; + let cmd = &TestMetadata::match_package(package, backend); + if let Err(err) = command_parser(&cmd, false) { + error_messages.push(err); + } + + if !error_messages.is_empty() { + for err in error_messages { + error!("{err}"); + } + } + } + } + Ok(()) +} + +/// Use mdbook to build the book +pub fn cargo_book(cargoarg: &Option<&str>) -> anyhow::Result<()> { + command_parser( + &CargoCommand::Book { + mdbookarg: cargoarg, + }, + false, + )?; + Ok(()) +} + +/// Run examples +/// +/// Supports updating the expected output via the overwrite argument +pub fn run_test( + cargoarg: &Option<&str>, + backend: Backends, + examples: &[String], + overwrite: bool, +) -> anyhow::Result<()> { + 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() + )), + mode: BuildMode::Release, + }; + if let Err(err) = command_parser(&cmd, false) { + error!("{err}"); + } + + let cmd = CargoCommand::Qemu { + cargoarg, + example, + target: backend.to_target(), + features: Some(format!( + "{},{}", + DEFAULT_FEATURES, + backend.to_rtic_feature() + )), + mode: BuildMode::Release, + }; + + if let Err(err) = command_parser(&cmd, overwrite) { + error!("{err}"); + } + }); + + Ok(()) +} + +/// Check the binary sizes of examples +pub fn build_and_check_size( + cargoarg: &Option<&str>, + backend: Backends, + examples: &[String], + size_arguments: &Option, +) -> anyhow::Result<()> { + 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() + )), + mode: BuildMode::Release, + }; + if let Err(err) = command_parser(&cmd, false) { + error!("{err}"); + } + + let cmd = CargoCommand::ExampleSize { + cargoarg, + example, + target: backend.to_target(), + features: Some(format!( + "{},{}", + DEFAULT_FEATURES, + backend.to_rtic_feature() + )), + mode: BuildMode::Release, + arguments: size_arguments.clone(), + }; + if let Err(err) = command_parser(&cmd, false) { + error!("{err}"); + } + }); + + Ok(()) +} diff --git a/xtask/src/main.rs b/xtask/src/main.rs index 34d4d0a0f7..6bf93176df 100644 --- a/xtask/src/main.rs +++ b/xtask/src/main.rs @@ -1,13 +1,13 @@ mod argument_parsing; mod build; +mod cargo_commands; mod command; use anyhow::bail; -use argument_parsing::{Package, Sizearguments, TestMetadata}; +use argument_parsing::{Package, Sizearguments}; use clap::Parser; use core::fmt; use diffy::{create_patch, PatchFormatter}; -use rayon::prelude::*; use std::{ error::Error, ffi::OsString, @@ -25,7 +25,11 @@ use log::{debug, error, info, log_enabled, trace, Level}; use crate::{ argument_parsing::{Backends, BuildOrCheck, Cli, Commands, PackageOpt}, build::init_build_dir, - command::{run_command, run_successful, BuildMode, CargoCommand}, + cargo_commands::{ + 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}, }; // x86_64-unknown-linux-gnu @@ -260,251 +264,6 @@ fn main() -> anyhow::Result<()> { Ok(()) } -fn cargo( - operation: BuildOrCheck, - cargoarg: &Option<&str>, - package: &PackageOpt, - backend: Backends, -) -> anyhow::Result<()> { - let features = package_feature_extractor(package, backend); - - let command = match operation { - BuildOrCheck::Check => CargoCommand::Check { - cargoarg, - package: package.package, - target: backend.to_target(), - features, - mode: BuildMode::Release, - }, - BuildOrCheck::Build => CargoCommand::Build { - cargoarg, - package: package.package, - target: backend.to_target(), - features, - mode: BuildMode::Release, - }, - }; - command_parser(&command, false)?; - Ok(()) -} - -fn cargo_example( - operation: BuildOrCheck, - cargoarg: &Option<&str>, - backend: Backends, - examples: &[String], -) -> anyhow::Result<()> { - examples.into_par_iter().for_each(|example| { - let features = Some(format!( - "{},{}", - DEFAULT_FEATURES, - backend.to_rtic_feature() - )); - - let command = match operation { - BuildOrCheck::Check => CargoCommand::ExampleCheck { - cargoarg, - example, - target: backend.to_target(), - features, - mode: BuildMode::Release, - }, - BuildOrCheck::Build => CargoCommand::ExampleBuild { - cargoarg, - example, - target: backend.to_target(), - features, - mode: BuildMode::Release, - }, - }; - - if let Err(err) = command_parser(&command, false) { - error!("{err}"); - } - }); - - Ok(()) -} - -fn cargo_clippy( - cargoarg: &Option<&str>, - package: &PackageOpt, - backend: Backends, -) -> anyhow::Result<()> { - let features = package_feature_extractor(package, backend); - command_parser( - &CargoCommand::Clippy { - cargoarg, - package: package.package, - target: backend.to_target(), - features, - }, - false, - )?; - Ok(()) -} - -fn cargo_format( - cargoarg: &Option<&str>, - package: &PackageOpt, - check_only: bool, -) -> anyhow::Result<()> { - command_parser( - &CargoCommand::Format { - cargoarg, - package: package.package, - check_only, - }, - false, - )?; - Ok(()) -} - -fn cargo_doc(cargoarg: &Option<&str>, backend: Backends) -> anyhow::Result<()> { - let features = Some(format!( - "{},{}", - DEFAULT_FEATURES, - backend.to_rtic_feature() - )); - - command_parser(&CargoCommand::Doc { cargoarg, features }, false)?; - Ok(()) -} - -fn cargo_test(package: &PackageOpt, backend: Backends) -> anyhow::Result<()> { - if let Some(package) = package.package { - let cmd = match package { - Package::Rtic => TestMetadata::match_package(package, backend), - Package::RticArbiter => TestMetadata::match_package(package, backend), - Package::RticChannel => TestMetadata::match_package(package, backend), - Package::RticCommon => TestMetadata::match_package(package, backend), - Package::RticMacros => TestMetadata::match_package(package, backend), - Package::RticMonotonics => TestMetadata::match_package(package, backend), - Package::RticTime => TestMetadata::match_package(package, backend), - }; - command_parser(&cmd, false)?; - } else { - // Iterate over all workspace packages - for package in [ - Package::Rtic, - Package::RticArbiter, - Package::RticChannel, - Package::RticCommon, - Package::RticMacros, - Package::RticMonotonics, - Package::RticTime, - ] { - let mut error_messages = vec![]; - let cmd = &TestMetadata::match_package(package, backend); - if let Err(err) = command_parser(&cmd, false) { - error_messages.push(err); - } - - if !error_messages.is_empty() { - for err in error_messages { - error!("{err}"); - } - } - } - } - Ok(()) -} - -fn cargo_book(cargoarg: &Option<&str>) -> anyhow::Result<()> { - command_parser( - &CargoCommand::Book { - mdbookarg: cargoarg, - }, - false, - )?; - Ok(()) -} - -fn run_test( - cargoarg: &Option<&str>, - backend: Backends, - examples: &[String], - overwrite: bool, -) -> anyhow::Result<()> { - 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() - )), - mode: BuildMode::Release, - }; - if let Err(err) = command_parser(&cmd, false) { - error!("{err}"); - } - - let cmd = CargoCommand::Qemu { - cargoarg, - example, - target: backend.to_target(), - features: Some(format!( - "{},{}", - DEFAULT_FEATURES, - backend.to_rtic_feature() - )), - mode: BuildMode::Release, - }; - - if let Err(err) = command_parser(&cmd, overwrite) { - error!("{err}"); - } - }); - - Ok(()) -} - -fn build_and_check_size( - cargoarg: &Option<&str>, - backend: Backends, - examples: &[String], - size_arguments: &Option, -) -> anyhow::Result<()> { - 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() - )), - mode: BuildMode::Release, - }; - if let Err(err) = command_parser(&cmd, false) { - error!("{err}"); - } - - let cmd = CargoCommand::ExampleSize { - cargoarg, - example, - target: backend.to_target(), - features: Some(format!( - "{},{}", - DEFAULT_FEATURES, - backend.to_rtic_feature() - )), - mode: BuildMode::Release, - arguments: size_arguments.clone(), - }; - if let Err(err) = command_parser(&cmd, false) { - error!("{err}"); - } - }); - - Ok(()) -} - /// Get the features needed given the selected package /// /// Without package specified the features for RTIC are required