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:
Román Cárdenas Rodríguez 2024-03-20 21:06:47 +01:00 committed by GitHub
parent 22ac33a826
commit 4060c3def8
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
166 changed files with 2322 additions and 315 deletions

View file

@ -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)]

View file

@ -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
}

View file

@ -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"))

View file

@ -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,
};