mirror of
https://github.com/rtic-rs/rtic.git
synced 2025-12-16 21:05:35 +01:00
RISC-V support over CLINT (#815)
* Rebase to master * using interrupt_mod * bug fixes * fix other backends * Add changelog * forgot about rtic-macros * backend-specific configuration * core peripherals optional over macro argument * pre_init_preprocessing binding * CI for RISC-V (WIP) * separation of concerns * add targets for RISC-V examples * remove qemu feature * prepare examples folder * move examples all together * move ci out of examples * minor changes * add cortex-m * new xtask: proof of concept * fix build.yml * feature typo * clean rtic examples * reproduce weird issue * remove unsafe code in user app * update dependencies * allow builds on riscv32imc * let's fix QEMU * Update .github/workflows/build.yml Co-authored-by: Henrik Tjäder <henrik@tjaders.com> * New build.rs * removing test features * adapt ui test to new version of clippy * add more examples to RISC-V backend * proper configuration of heapless for riscv32imc * opt-out examples for riscv32imc * point to new version of riscv-slic * adapt new macro bindings * adapt examples and CI to stable * fix cortex-m CI * Review --------- Co-authored-by: Henrik Tjäder <henrik@tjaders.com>
This commit is contained in:
parent
22ac33a826
commit
4060c3def8
166 changed files with 2322 additions and 315 deletions
|
|
@ -1,4 +1,7 @@
|
|||
use crate::{cargo_command::CargoCommand, Target, ARMV6M, ARMV7M, ARMV8MBASE, ARMV8MMAIN};
|
||||
use crate::{
|
||||
cargo_command::CargoCommand, Target, ARMV6M, ARMV7M, ARMV8MBASE, ARMV8MMAIN, RISCV32IMAC,
|
||||
RISCV32IMC,
|
||||
};
|
||||
use clap::{Args, Parser, Subcommand};
|
||||
use core::fmt;
|
||||
|
||||
|
|
@ -84,7 +87,7 @@ impl Package {
|
|||
};
|
||||
|
||||
features
|
||||
.into_iter()
|
||||
.iter()
|
||||
.map(ToString::to_string)
|
||||
.map(Some)
|
||||
.chain(std::iter::once(None))
|
||||
|
|
@ -101,12 +104,7 @@ impl TestMetadata {
|
|||
pub fn match_package(package: Package, backend: Backends) -> CargoCommand<'static> {
|
||||
match package {
|
||||
Package::Rtic => {
|
||||
let features = format!(
|
||||
"{},{}",
|
||||
backend.to_rtic_feature(),
|
||||
backend.to_rtic_uitest_feature()
|
||||
);
|
||||
let features = Some(backend.to_target().and_features(&features));
|
||||
let features = Some(backend.to_target().and_features(backend.to_rtic_feature()));
|
||||
CargoCommand::Test {
|
||||
package: Some(package.name()),
|
||||
features,
|
||||
|
|
@ -155,6 +153,9 @@ pub enum Backends {
|
|||
Thumbv7,
|
||||
Thumbv8Base,
|
||||
Thumbv8Main,
|
||||
RiscvEsp32C3,
|
||||
Riscv32ImcClint, // not working yet (issues with portable-atomic features...)
|
||||
Riscv32ImacClint,
|
||||
}
|
||||
|
||||
impl Backends {
|
||||
|
|
@ -165,6 +166,8 @@ impl Backends {
|
|||
Backends::Thumbv7 => ARMV7M,
|
||||
Backends::Thumbv8Base => ARMV8MBASE,
|
||||
Backends::Thumbv8Main => ARMV8MMAIN,
|
||||
Backends::Riscv32ImcClint => RISCV32IMC,
|
||||
Backends::RiscvEsp32C3 | Backends::Riscv32ImacClint => RISCV32IMAC,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -175,6 +178,8 @@ impl Backends {
|
|||
Backends::Thumbv7 => "thumbv7-backend",
|
||||
Backends::Thumbv8Base => "thumbv8base-backend",
|
||||
Backends::Thumbv8Main => "thumbv8main-backend",
|
||||
Backends::RiscvEsp32C3 => "riscv-esp32c3-backend",
|
||||
Backends::Riscv32ImcClint | Backends::Riscv32ImacClint => "riscv-clint-backend",
|
||||
}
|
||||
}
|
||||
#[allow(clippy::wrong_self_convention)]
|
||||
|
|
@ -182,13 +187,8 @@ impl Backends {
|
|||
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) -> &'static str {
|
||||
match self {
|
||||
Backends::Thumbv6 | Backends::Thumbv8Base => "rtic-uitestv6",
|
||||
Backends::Thumbv7 | Backends::Thumbv8Main => "rtic-uitestv7",
|
||||
Backends::RiscvEsp32C3 => "riscv-esp32c3",
|
||||
Backends::Riscv32ImcClint | Backends::Riscv32ImacClint => "riscv-clint",
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -200,14 +200,127 @@ pub enum BuildOrCheck {
|
|||
Build,
|
||||
}
|
||||
|
||||
#[derive(clap::ValueEnum, Copy, Clone, Default, Debug)]
|
||||
pub enum Platforms {
|
||||
Hifive1,
|
||||
#[default]
|
||||
Lm3s6965,
|
||||
Nrf52840,
|
||||
Rp2040,
|
||||
Stm32f3,
|
||||
Stm32f411,
|
||||
Teensy4,
|
||||
}
|
||||
|
||||
impl Platforms {
|
||||
pub fn name(&self) -> String {
|
||||
let name = match self {
|
||||
Platforms::Hifive1 => "hifive1",
|
||||
Platforms::Lm3s6965 => "lm3s6965",
|
||||
Platforms::Nrf52840 => "nrf52840",
|
||||
Platforms::Rp2040 => "rp2040",
|
||||
Platforms::Stm32f3 => "stm32f3",
|
||||
Platforms::Stm32f411 => "stm32f411",
|
||||
Platforms::Teensy4 => "teensy4",
|
||||
};
|
||||
name.to_string()
|
||||
}
|
||||
|
||||
/// Rust flags needed for the platform when building
|
||||
pub fn rust_flags(&self) -> Vec<String> {
|
||||
let c = "-C".to_string();
|
||||
match self {
|
||||
Platforms::Hifive1 => vec![c, "link-arg=-Thifive1-link.x".to_string()],
|
||||
Platforms::Lm3s6965 => vec![c, "link-arg=-Tlink.x".to_string()],
|
||||
Platforms::Nrf52840 => vec![
|
||||
c.clone(),
|
||||
"linker=flip-link".to_string(),
|
||||
c.clone(),
|
||||
"link-arg=-Tlink.x".to_string(),
|
||||
c.clone(),
|
||||
"link-arg=-Tdefmt.x".to_string(),
|
||||
c,
|
||||
"link-arg=--nmagic".to_string(),
|
||||
],
|
||||
Platforms::Rp2040 => vec![
|
||||
c.clone(),
|
||||
"link-arg=--nmagic".to_string(),
|
||||
c,
|
||||
"link-arg=-Tlink.x".to_string(),
|
||||
],
|
||||
Platforms::Stm32f3 => vec![
|
||||
c.clone(),
|
||||
"link-arg=--nmagic".to_string(),
|
||||
c,
|
||||
"link-arg=-Tlink.x".to_string(),
|
||||
],
|
||||
Platforms::Stm32f411 => vec![
|
||||
c.clone(),
|
||||
"link-arg=-Tlink.x".to_string(),
|
||||
c,
|
||||
"link-arg=-Tdefmt.x".to_string(),
|
||||
],
|
||||
Platforms::Teensy4 => vec![c, "link-arg=-Tt4link.x".to_string()],
|
||||
}
|
||||
}
|
||||
|
||||
/// Get the default backend for the platform
|
||||
pub fn default_backend(&self) -> Backends {
|
||||
match self {
|
||||
Platforms::Hifive1 => Backends::Riscv32ImcClint,
|
||||
Platforms::Lm3s6965 => Backends::Thumbv7,
|
||||
Platforms::Nrf52840 => unimplemented!(),
|
||||
Platforms::Rp2040 => unimplemented!(),
|
||||
Platforms::Stm32f3 => unimplemented!(),
|
||||
Platforms::Stm32f411 => unimplemented!(),
|
||||
Platforms::Teensy4 => unimplemented!(),
|
||||
}
|
||||
}
|
||||
|
||||
/// Get the features needed given the selected platform and backend.
|
||||
/// If the backend is not supported for the platform, return Err.
|
||||
/// If the backend is supported, but no special features are needed, return Ok(None).
|
||||
pub fn features(&self, backend: &Backends) -> Result<Option<&'static str>, ()> {
|
||||
match self {
|
||||
Platforms::Hifive1 => match backend.to_target() {
|
||||
RISCV32IMC | RISCV32IMAC => Ok(None),
|
||||
_ => Err(()),
|
||||
},
|
||||
Platforms::Lm3s6965 => match backend.to_target() {
|
||||
ARMV6M => Ok(Some("thumbv6-backend")),
|
||||
ARMV7M => Ok(Some("thumbv7-backend")),
|
||||
ARMV8MBASE => Ok(Some("thumbv8base-backend")),
|
||||
ARMV8MMAIN => Ok(Some("thumbv8main-backend")),
|
||||
_ => Err(()),
|
||||
},
|
||||
Platforms::Nrf52840 => unimplemented!(),
|
||||
Platforms::Rp2040 => unimplemented!(),
|
||||
Platforms::Stm32f3 => unimplemented!(),
|
||||
Platforms::Stm32f411 => unimplemented!(),
|
||||
Platforms::Teensy4 => unimplemented!(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Parser, Clone)]
|
||||
pub struct Globals {
|
||||
/// Error out on warnings
|
||||
#[arg(short = 'D', long)]
|
||||
pub deny_warnings: bool,
|
||||
|
||||
/// For which platform to build.
|
||||
///
|
||||
/// If omitted, the default platform (i.e., lm3s6965) is used.
|
||||
///
|
||||
/// Example: `cargo xtask --platform lm3s6965`
|
||||
#[arg(value_enum, short, default_value = "lm3s6965", long, global = true)]
|
||||
pub platform: Option<Platforms>,
|
||||
|
||||
/// For which backend to build.
|
||||
#[arg(value_enum, short, default_value = "thumbv7", long, global = true)]
|
||||
///
|
||||
/// If omitted, the default backend for the selected platform is used
|
||||
/// (check [`Platforms::default_backend`]).
|
||||
#[arg(value_enum, short, long, global = true)]
|
||||
pub backend: Option<Backends>,
|
||||
|
||||
/// List of comma separated examples to include, all others are excluded
|
||||
|
|
@ -316,55 +429,6 @@ pub enum Commands {
|
|||
|
||||
/// Build books with mdbook
|
||||
Book(Arg),
|
||||
|
||||
/// Check one or more usage examples.
|
||||
///
|
||||
/// Usage examples are located in ./examples
|
||||
UsageExampleCheck(UsageExamplesOpt),
|
||||
|
||||
/// Build one or more usage examples.
|
||||
///
|
||||
/// Usage examples are located in ./examples
|
||||
#[clap(alias = "./examples")]
|
||||
UsageExampleBuild(UsageExamplesOpt),
|
||||
}
|
||||
|
||||
#[derive(Args, Clone, Debug)]
|
||||
pub struct UsageExamplesOpt {
|
||||
/// The usage examples to build. All usage examples are selected if this argument is not provided.
|
||||
///
|
||||
/// Example: `rp2040_local_i2c_init,stm32f3_blinky`.
|
||||
examples: Option<String>,
|
||||
}
|
||||
|
||||
impl UsageExamplesOpt {
|
||||
pub fn examples(&self) -> anyhow::Result<Vec<String>> {
|
||||
let usage_examples: Vec<_> = std::fs::read_dir("./examples")?
|
||||
.filter_map(Result::ok)
|
||||
.filter(|p| p.metadata().ok().map(|p| p.is_dir()).unwrap_or(false))
|
||||
.filter_map(|p| p.file_name().to_str().map(ToString::to_string))
|
||||
.collect();
|
||||
|
||||
let selected_examples: Option<Vec<String>> = self
|
||||
.examples
|
||||
.clone()
|
||||
.map(|s| s.split(",").map(ToString::to_string).collect());
|
||||
|
||||
if let Some(selected_examples) = selected_examples {
|
||||
if let Some(unfound_example) = selected_examples
|
||||
.iter()
|
||||
.find(|e| !usage_examples.contains(e))
|
||||
{
|
||||
Err(anyhow::anyhow!(
|
||||
"Usage example {unfound_example} does not exist"
|
||||
))
|
||||
} else {
|
||||
Ok(selected_examples)
|
||||
}
|
||||
} else {
|
||||
Ok(usage_examples)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Args, Debug, Clone)]
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
use crate::{ExtraArguments, Target};
|
||||
use crate::{ExtraArguments, Platforms, Target};
|
||||
use core::fmt;
|
||||
use std::path::PathBuf;
|
||||
|
||||
|
|
@ -15,6 +15,7 @@ pub enum CargoCommand<'a> {
|
|||
#[allow(dead_code)]
|
||||
Run {
|
||||
cargoarg: &'a Option<&'a str>,
|
||||
platform: Platforms, // to tell which platform. If None, it assumes lm3s6965
|
||||
example: &'a str,
|
||||
target: Option<Target<'a>>,
|
||||
features: Option<String>,
|
||||
|
|
@ -23,6 +24,7 @@ pub enum CargoCommand<'a> {
|
|||
},
|
||||
Qemu {
|
||||
cargoarg: &'a Option<&'a str>,
|
||||
platform: Platforms, // to tell which platform. If None, it assumes lm3s6965
|
||||
example: &'a str,
|
||||
target: Option<Target<'a>>,
|
||||
features: Option<String>,
|
||||
|
|
@ -32,6 +34,7 @@ pub enum CargoCommand<'a> {
|
|||
},
|
||||
ExampleBuild {
|
||||
cargoarg: &'a Option<&'a str>,
|
||||
platform: Platforms, // to tell which platform. If None, it assumes lm3s6965
|
||||
example: &'a str,
|
||||
target: Option<Target<'a>>,
|
||||
features: Option<String>,
|
||||
|
|
@ -41,10 +44,12 @@ pub enum CargoCommand<'a> {
|
|||
},
|
||||
ExampleCheck {
|
||||
cargoarg: &'a Option<&'a str>,
|
||||
platform: Platforms, // to tell which platform. If None, it assumes lm3s6965
|
||||
example: &'a str,
|
||||
target: Option<Target<'a>>,
|
||||
features: Option<String>,
|
||||
mode: BuildMode,
|
||||
dir: Option<PathBuf>,
|
||||
deny_warnings: bool,
|
||||
},
|
||||
Build {
|
||||
|
|
@ -94,6 +99,7 @@ pub enum CargoCommand<'a> {
|
|||
},
|
||||
ExampleSize {
|
||||
cargoarg: &'a Option<&'a str>,
|
||||
platform: Platforms, // to tell which platform. If None, it assumes lm3s6965
|
||||
example: &'a str,
|
||||
target: Option<Target<'a>>,
|
||||
features: Option<String>,
|
||||
|
|
@ -137,6 +143,7 @@ impl core::fmt::Display for CargoCommand<'_> {
|
|||
features: &Option<String>,
|
||||
cargoarg: &&Option<&str>,
|
||||
path: Option<&PathBuf>,
|
||||
// no need to add platform, as it is implicit in the path
|
||||
) -> String {
|
||||
let feat = feat(features);
|
||||
let carg = carg(cargoarg);
|
||||
|
|
@ -179,6 +186,7 @@ impl core::fmt::Display for CargoCommand<'_> {
|
|||
match self {
|
||||
CargoCommand::Run {
|
||||
cargoarg,
|
||||
platform: _,
|
||||
example,
|
||||
target,
|
||||
features,
|
||||
|
|
@ -193,6 +201,7 @@ impl core::fmt::Display for CargoCommand<'_> {
|
|||
}
|
||||
CargoCommand::Qemu {
|
||||
cargoarg,
|
||||
platform: _,
|
||||
example,
|
||||
target,
|
||||
features,
|
||||
|
|
@ -206,6 +215,7 @@ impl core::fmt::Display for CargoCommand<'_> {
|
|||
}
|
||||
CargoCommand::ExampleBuild {
|
||||
cargoarg,
|
||||
platform: _,
|
||||
example,
|
||||
target,
|
||||
features,
|
||||
|
|
@ -219,16 +229,18 @@ impl core::fmt::Display for CargoCommand<'_> {
|
|||
}
|
||||
CargoCommand::ExampleCheck {
|
||||
cargoarg,
|
||||
platform: _,
|
||||
example,
|
||||
target,
|
||||
features,
|
||||
mode,
|
||||
dir,
|
||||
deny_warnings,
|
||||
} => write!(
|
||||
f,
|
||||
"Check example {example} {}",
|
||||
details(*deny_warnings, target, Some(mode), features, cargoarg, None)
|
||||
),
|
||||
} => {
|
||||
let warns = *deny_warnings;
|
||||
let details = details(warns, target, Some(mode), features, cargoarg, dir.as_ref());
|
||||
write!(f, "Check example {example} {details}",)
|
||||
}
|
||||
CargoCommand::Build {
|
||||
cargoarg,
|
||||
package,
|
||||
|
|
@ -329,17 +341,14 @@ impl core::fmt::Display for CargoCommand<'_> {
|
|||
.clone()
|
||||
.map(|t| format!("test {t}"))
|
||||
.unwrap_or("all tests".into());
|
||||
let deny_warnings = if *deny_warnings {
|
||||
format!("deny warnings, ")
|
||||
} else {
|
||||
format!("")
|
||||
};
|
||||
let feat = feat(features);
|
||||
write!(f, "Run {test} in {p} ({deny_warnings}features: {feat})")
|
||||
|
||||
let details = details(*deny_warnings, &None, None, features, &&None, None);
|
||||
write!(f, "Run {test} in {p} {details}")
|
||||
}
|
||||
CargoCommand::Book { arguments: _ } => write!(f, "Build the book"),
|
||||
CargoCommand::ExampleSize {
|
||||
cargoarg,
|
||||
platform: _,
|
||||
example,
|
||||
target,
|
||||
features,
|
||||
|
|
@ -475,6 +484,7 @@ impl<'a> CargoCommand<'a> {
|
|||
// For future embedded-ci, for now the same as Qemu
|
||||
CargoCommand::Run {
|
||||
cargoarg,
|
||||
platform: _,
|
||||
example,
|
||||
features,
|
||||
mode,
|
||||
|
|
@ -491,6 +501,7 @@ impl<'a> CargoCommand<'a> {
|
|||
),
|
||||
CargoCommand::Qemu {
|
||||
cargoarg,
|
||||
platform: _,
|
||||
example,
|
||||
features,
|
||||
mode,
|
||||
|
|
@ -606,6 +617,7 @@ impl<'a> CargoCommand<'a> {
|
|||
}
|
||||
CargoCommand::ExampleBuild {
|
||||
cargoarg,
|
||||
platform: _,
|
||||
example,
|
||||
features,
|
||||
mode,
|
||||
|
|
@ -624,9 +636,11 @@ impl<'a> CargoCommand<'a> {
|
|||
),
|
||||
CargoCommand::ExampleCheck {
|
||||
cargoarg,
|
||||
platform: _,
|
||||
example,
|
||||
features,
|
||||
mode,
|
||||
dir: _,
|
||||
// Target is added by build_args
|
||||
target: _,
|
||||
// deny_warnings is exposed through `extra_env`
|
||||
|
|
@ -640,6 +654,7 @@ impl<'a> CargoCommand<'a> {
|
|||
),
|
||||
CargoCommand::ExampleSize {
|
||||
cargoarg,
|
||||
platform: _,
|
||||
example,
|
||||
features,
|
||||
mode,
|
||||
|
|
@ -664,6 +679,7 @@ impl<'a> CargoCommand<'a> {
|
|||
pub fn chdir(&self) -> Option<&PathBuf> {
|
||||
match self {
|
||||
CargoCommand::Qemu { dir, .. }
|
||||
| CargoCommand::ExampleCheck { dir, .. }
|
||||
| CargoCommand::ExampleBuild { dir, .. }
|
||||
| CargoCommand::ExampleSize { dir, .. }
|
||||
| CargoCommand::Build { dir, .. }
|
||||
|
|
@ -687,20 +703,35 @@ impl<'a> CargoCommand<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn extra_env(&self) -> Option<(&str, &str)> {
|
||||
pub fn extra_env(&self) -> Option<(&str, String)> {
|
||||
match self {
|
||||
// Clippy is a special case: it sets deny warnings
|
||||
// through an argument to rustc.
|
||||
CargoCommand::Clippy { .. } => None,
|
||||
CargoCommand::Doc { .. } => Some(("RUSTDOCFLAGS", "-D warnings")),
|
||||
CargoCommand::Doc { .. } => Some(("RUSTDOCFLAGS", "-D warnings".to_string())),
|
||||
|
||||
CargoCommand::Qemu { deny_warnings, .. }
|
||||
| CargoCommand::ExampleBuild { deny_warnings, .. }
|
||||
| CargoCommand::ExampleSize { deny_warnings, .. } => {
|
||||
CargoCommand::Qemu {
|
||||
platform,
|
||||
deny_warnings,
|
||||
..
|
||||
}
|
||||
| CargoCommand::ExampleBuild {
|
||||
platform,
|
||||
deny_warnings,
|
||||
..
|
||||
}
|
||||
| CargoCommand::ExampleSize {
|
||||
platform,
|
||||
deny_warnings,
|
||||
..
|
||||
} => {
|
||||
if *deny_warnings {
|
||||
let rust_flags = platform.rust_flags().join(" ");
|
||||
let rust_flags = format!("-D warnings {}", rust_flags);
|
||||
// NOTE: this also needs the link-arg because .cargo/config.toml
|
||||
// is ignored if you set the RUSTFLAGS env variable.
|
||||
Some(("RUSTFLAGS", "-D warnings -C link-arg=-Tlink.x"))
|
||||
Some(("RUSTFLAGS", rust_flags))
|
||||
// TODO make this configurable
|
||||
} else {
|
||||
None
|
||||
}
|
||||
|
|
@ -711,7 +742,7 @@ impl<'a> CargoCommand<'a> {
|
|||
| CargoCommand::Build { deny_warnings, .. }
|
||||
| CargoCommand::Test { deny_warnings, .. } => {
|
||||
if *deny_warnings {
|
||||
Some(("RUSTFLAGS", "-D warnings"))
|
||||
Some(("RUSTFLAGS", "-D warnings".to_string()))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,12 +11,12 @@ use std::{path::Path, str};
|
|||
use log::{error, info, log_enabled, trace, Level};
|
||||
|
||||
use crate::{
|
||||
argument_parsing::{Backends, BuildOrCheck, Cli, Commands},
|
||||
argument_parsing::{BuildOrCheck, Cli, Commands, Platforms},
|
||||
build::init_build_dir,
|
||||
run::*,
|
||||
};
|
||||
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
#[derive(Debug, Clone, Copy, Eq, PartialEq)]
|
||||
pub struct Target<'a> {
|
||||
triple: &'a str,
|
||||
has_std: bool,
|
||||
|
|
@ -54,6 +54,8 @@ 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);
|
||||
const RISCV32IMC: Target = Target::new("riscv32imc-unknown-none-elf", false);
|
||||
const RISCV32IMAC: Target = Target::new("riscv32imac-unknown-none-elf", false);
|
||||
|
||||
fn main() -> anyhow::Result<()> {
|
||||
// if there's an `xtask` folder, we're *probably* at the root of this repo (we can't just
|
||||
|
|
@ -65,13 +67,6 @@ fn main() -> anyhow::Result<()> {
|
|||
));
|
||||
}
|
||||
|
||||
let examples: Vec<_> = std::fs::read_dir("./rtic/examples")?
|
||||
.filter_map(|p| p.ok())
|
||||
.map(|p| p.path())
|
||||
.filter(|p| p.display().to_string().ends_with(".rs"))
|
||||
.map(|path| path.file_stem().unwrap().to_str().unwrap().to_string())
|
||||
.collect();
|
||||
|
||||
let cli = Cli::parse();
|
||||
|
||||
let globals = &cli.globals;
|
||||
|
|
@ -94,12 +89,35 @@ fn main() -> anyhow::Result<()> {
|
|||
);
|
||||
log::debug!("Partial features: {}", globals.partial);
|
||||
|
||||
let platform = if let Some(platform) = globals.platform {
|
||||
platform
|
||||
} else {
|
||||
Platforms::default()
|
||||
};
|
||||
|
||||
let backend = if let Some(backend) = globals.backend {
|
||||
backend
|
||||
} else {
|
||||
Backends::default()
|
||||
platform.default_backend()
|
||||
};
|
||||
|
||||
// Check if the platform supports the backend
|
||||
if platform.features(&backend).is_err() {
|
||||
return Err(anyhow::anyhow!(
|
||||
"platform {:?} does not support backend {:?}",
|
||||
platform,
|
||||
backend
|
||||
));
|
||||
}
|
||||
|
||||
let examples_path = format!("./examples/{}/examples", platform.name());
|
||||
let examples: Vec<_> = std::fs::read_dir(examples_path)?
|
||||
.filter_map(|p| p.ok())
|
||||
.map(|p| p.path())
|
||||
.filter(|p| p.display().to_string().ends_with(".rs"))
|
||||
.map(|path| path.file_stem().unwrap().to_str().unwrap().to_string())
|
||||
.collect();
|
||||
|
||||
let example = globals.example.clone();
|
||||
let exampleexclude = globals.exampleexclude.clone();
|
||||
|
||||
|
|
@ -163,42 +181,45 @@ fn main() -> anyhow::Result<()> {
|
|||
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)
|
||||
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:?}");
|
||||
info!("Checking on platform: {platform:?}, backend: {backend:?}");
|
||||
cargo_example(
|
||||
globals,
|
||||
BuildOrCheck::Check,
|
||||
&cargologlevel,
|
||||
platform,
|
||||
backend,
|
||||
&examples_to_run,
|
||||
)
|
||||
}
|
||||
Commands::ExampleBuild => {
|
||||
info!("Building for backend: {backend:?}");
|
||||
info!("Building for platform: {platform:?}, backend: {backend:?}");
|
||||
cargo_example(
|
||||
globals,
|
||||
BuildOrCheck::Build,
|
||||
&cargologlevel,
|
||||
platform,
|
||||
backend,
|
||||
&examples_to_run,
|
||||
)
|
||||
}
|
||||
Commands::Size(args) => {
|
||||
// x86_64 target not valid
|
||||
info!("Measuring for backend: {backend:?}");
|
||||
info!("Measuring for platform: {platform:?}, backend: {backend:?}");
|
||||
build_and_check_size(
|
||||
globals,
|
||||
&cargologlevel,
|
||||
platform,
|
||||
backend,
|
||||
&examples_to_run,
|
||||
&args.arguments,
|
||||
|
|
@ -206,10 +227,11 @@ fn main() -> anyhow::Result<()> {
|
|||
}
|
||||
Commands::Qemu(args) | Commands::Run(args) => {
|
||||
// x86_64 target not valid
|
||||
info!("Testing for backend: {backend:?}");
|
||||
info!("Testing for platform: {platform:?}, backend: {backend:?}");
|
||||
qemu_run_examples(
|
||||
globals,
|
||||
&cargologlevel,
|
||||
platform,
|
||||
backend,
|
||||
&examples_to_run,
|
||||
args.overwrite_expected,
|
||||
|
|
@ -221,20 +243,12 @@ fn main() -> anyhow::Result<()> {
|
|||
}
|
||||
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)
|
||||
}
|
||||
Commands::UsageExampleCheck(examples) => {
|
||||
info!("Checking usage examples");
|
||||
cargo_usage_example(globals, BuildOrCheck::Check, examples.examples()?)
|
||||
}
|
||||
Commands::UsageExampleBuild(examples) => {
|
||||
info!("Building usage examples");
|
||||
cargo_usage_example(globals, BuildOrCheck::Build, examples.examples()?)
|
||||
}
|
||||
};
|
||||
|
||||
handle_results(globals, final_run_results).map_err(|_| anyhow::anyhow!("Commands failed"))
|
||||
|
|
|
|||
|
|
@ -15,7 +15,9 @@ mod iter;
|
|||
use iter::{into_iter, CoalescingRunner};
|
||||
|
||||
use crate::{
|
||||
argument_parsing::{Backends, BuildOrCheck, ExtraArguments, Globals, PackageOpt, TestMetadata},
|
||||
argument_parsing::{
|
||||
Backends, BuildOrCheck, ExtraArguments, Globals, PackageOpt, Platforms, TestMetadata,
|
||||
},
|
||||
cargo_command::{BuildMode, CargoCommand},
|
||||
};
|
||||
|
||||
|
|
@ -62,7 +64,12 @@ fn command_parser(
|
|||
};
|
||||
|
||||
match *command {
|
||||
CargoCommand::Qemu { example, .. } | CargoCommand::Run { example, .. } => {
|
||||
CargoCommand::Qemu {
|
||||
platform, example, ..
|
||||
}
|
||||
| CargoCommand::Run {
|
||||
platform, example, ..
|
||||
} => {
|
||||
/// Check if `run` was successful.
|
||||
/// returns Ok in case the run went as expected,
|
||||
/// Err otherwise
|
||||
|
|
@ -99,8 +106,9 @@ fn command_parser(
|
|||
res
|
||||
}
|
||||
|
||||
let platform_name = platform.name();
|
||||
let run_file = format!("{example}.run");
|
||||
let expected_output_file = ["rtic", "ci", "expected", &run_file]
|
||||
let expected_output_file = ["ci", "expected", &platform_name, &run_file]
|
||||
.iter()
|
||||
.collect::<PathBuf>()
|
||||
.into_os_string()
|
||||
|
|
@ -191,72 +199,41 @@ pub fn cargo<'c>(
|
|||
runner.run_and_coalesce()
|
||||
}
|
||||
|
||||
/// Cargo command to build a usage example.
|
||||
///
|
||||
/// The usage examples are in examples/
|
||||
pub fn cargo_usage_example(
|
||||
globals: &Globals,
|
||||
operation: BuildOrCheck,
|
||||
usage_examples: Vec<String>,
|
||||
) -> Vec<FinalRunResult<'_>> {
|
||||
into_iter(&usage_examples)
|
||||
.map(|example| {
|
||||
let path = format!("examples/{example}");
|
||||
|
||||
let command = match operation {
|
||||
BuildOrCheck::Check => CargoCommand::Check {
|
||||
cargoarg: &None,
|
||||
mode: BuildMode::Release,
|
||||
dir: Some(path.into()),
|
||||
package: None,
|
||||
target: None,
|
||||
features: None,
|
||||
deny_warnings: globals.deny_warnings,
|
||||
},
|
||||
BuildOrCheck::Build => CargoCommand::Build {
|
||||
cargoarg: &None,
|
||||
package: None,
|
||||
target: None,
|
||||
features: None,
|
||||
mode: BuildMode::Release,
|
||||
dir: Some(path.into()),
|
||||
deny_warnings: globals.deny_warnings,
|
||||
},
|
||||
};
|
||||
(globals, command, false)
|
||||
})
|
||||
.run_and_coalesce()
|
||||
}
|
||||
|
||||
/// Cargo command to either build or check all examples
|
||||
///
|
||||
/// The examples are in rtic/examples
|
||||
/// The examples are in examples/<platform>/examples
|
||||
pub fn cargo_example<'c>(
|
||||
globals: &Globals,
|
||||
operation: BuildOrCheck,
|
||||
cargoarg: &'c Option<&'c str>,
|
||||
platform: Platforms,
|
||||
backend: Backends,
|
||||
examples: &'c [String],
|
||||
) -> Vec<FinalRunResult<'c>> {
|
||||
let runner = into_iter(examples).map(|example| {
|
||||
let path = format!("examples/{}", platform.name());
|
||||
let dir = Some(PathBuf::from(path));
|
||||
let features = Some(backend.to_target().and_features(backend.to_rtic_feature()));
|
||||
|
||||
let command = match operation {
|
||||
BuildOrCheck::Check => CargoCommand::ExampleCheck {
|
||||
cargoarg,
|
||||
platform,
|
||||
example,
|
||||
target: Some(backend.to_target()),
|
||||
features,
|
||||
mode: BuildMode::Release,
|
||||
dir,
|
||||
deny_warnings: globals.deny_warnings,
|
||||
},
|
||||
BuildOrCheck::Build => CargoCommand::ExampleBuild {
|
||||
cargoarg,
|
||||
platform,
|
||||
example,
|
||||
target: Some(backend.to_target()),
|
||||
features,
|
||||
mode: BuildMode::Release,
|
||||
dir: Some(PathBuf::from("./rtic")),
|
||||
dir,
|
||||
deny_warnings: globals.deny_warnings,
|
||||
},
|
||||
};
|
||||
|
|
@ -368,9 +345,12 @@ pub fn cargo_book<'c>(
|
|||
/// Run examples
|
||||
///
|
||||
/// Supports updating the expected output via the overwrite argument
|
||||
///
|
||||
/// The examples are in examples/<platform>/examples
|
||||
pub fn qemu_run_examples<'c>(
|
||||
globals: &Globals,
|
||||
cargoarg: &'c Option<&'c str>,
|
||||
platform: Platforms,
|
||||
backend: Backends,
|
||||
examples: &'c [String],
|
||||
overwrite: bool,
|
||||
|
|
@ -380,11 +360,13 @@ pub fn qemu_run_examples<'c>(
|
|||
|
||||
into_iter(examples)
|
||||
.flat_map(|example| {
|
||||
let path = format!("examples/{}", platform.name());
|
||||
let dir = Some(PathBuf::from(path));
|
||||
let target = target.into();
|
||||
let dir = Some(PathBuf::from("./rtic"));
|
||||
|
||||
let cmd_build = CargoCommand::ExampleBuild {
|
||||
cargoarg: &None,
|
||||
platform,
|
||||
example,
|
||||
target,
|
||||
features: features.clone(),
|
||||
|
|
@ -395,6 +377,7 @@ pub fn qemu_run_examples<'c>(
|
|||
|
||||
let cmd_qemu = CargoCommand::Qemu {
|
||||
cargoarg,
|
||||
platform,
|
||||
example,
|
||||
target,
|
||||
features: features.clone(),
|
||||
|
|
@ -413,6 +396,7 @@ pub fn qemu_run_examples<'c>(
|
|||
pub fn build_and_check_size<'c>(
|
||||
globals: &Globals,
|
||||
cargoarg: &'c Option<&'c str>,
|
||||
platform: Platforms,
|
||||
backend: Backends,
|
||||
examples: &'c [String],
|
||||
arguments: &'c Option<ExtraArguments>,
|
||||
|
|
@ -422,27 +406,31 @@ pub fn build_and_check_size<'c>(
|
|||
|
||||
let runner = into_iter(examples)
|
||||
.flat_map(|example| {
|
||||
let path = format!("examples/{}", platform.name());
|
||||
let dir = Some(PathBuf::from(path));
|
||||
let target = target.into();
|
||||
|
||||
// Make sure the requested example(s) are built
|
||||
let cmd_build = CargoCommand::ExampleBuild {
|
||||
cargoarg: &Some("--quiet"),
|
||||
platform,
|
||||
example,
|
||||
target,
|
||||
features: features.clone(),
|
||||
mode: BuildMode::Release,
|
||||
dir: Some(PathBuf::from("./rtic")),
|
||||
dir: dir.clone(),
|
||||
deny_warnings: globals.deny_warnings,
|
||||
};
|
||||
|
||||
let cmd_size = CargoCommand::ExampleSize {
|
||||
cargoarg,
|
||||
platform,
|
||||
example,
|
||||
target,
|
||||
features: features.clone(),
|
||||
mode: BuildMode::Release,
|
||||
arguments: arguments.clone(),
|
||||
dir: Some(PathBuf::from("./rtic")),
|
||||
dir,
|
||||
deny_warnings: globals.deny_warnings,
|
||||
};
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue