Build examples in debug mode (#2078)
* Build examples in debug mode * Allow building psram examples in debug mode in CI * Don't rebuild tests, try to avoid rebuilding dependencies
This commit is contained in:
parent
42a0417fba
commit
5370afb1eb
4
.github/actions/check-esp-hal/action.yml
vendored
4
.github/actions/check-esp-hal/action.yml
vendored
@ -57,5 +57,7 @@ runs:
|
|||||||
--target=${{ inputs.target }} \
|
--target=${{ inputs.target }} \
|
||||||
esp-hal
|
esp-hal
|
||||||
- name: Build (examples)
|
- name: Build (examples)
|
||||||
|
env:
|
||||||
|
CI: 1
|
||||||
shell: bash
|
shell: bash
|
||||||
run: cargo +${{ inputs.toolchain }} xtask build-examples esp-hal ${{ inputs.device }}
|
run: cargo +${{ inputs.toolchain }} xtask build-examples esp-hal ${{ inputs.device }} --debug
|
||||||
|
|||||||
@ -6,14 +6,14 @@ fn main() -> Result<(), String> {
|
|||||||
|
|
||||||
if cfg!(feature = "esp32") {
|
if cfg!(feature = "esp32") {
|
||||||
match std::env::var("OPT_LEVEL") {
|
match std::env::var("OPT_LEVEL") {
|
||||||
Ok(level) => {
|
Ok(level) if std::env::var("CI").is_err() => {
|
||||||
if level != "2" && level != "3" {
|
if level != "2" && level != "3" {
|
||||||
Err(format!("Building esp-storage for ESP32 needs optimization level 2 or 3 - yours is {}. See https://github.com/esp-rs/esp-storage", level))
|
Err(format!("Building esp-storage for ESP32 needs optimization level 2 or 3 - yours is {}. See https://github.com/esp-rs/esp-storage", level))
|
||||||
} else {
|
} else {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Err(_err) => Ok(()),
|
_ => Ok(()),
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|||||||
@ -8,4 +8,12 @@ fn main() {
|
|||||||
if cfg!(feature = "esp-wifi") {
|
if cfg!(feature = "esp-wifi") {
|
||||||
println!("cargo::rustc-link-arg=-Trom_functions.x");
|
println!("cargo::rustc-link-arg=-Trom_functions.x");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Allow building examples in CI in debug mode
|
||||||
|
println!("cargo:rustc-check-cfg=cfg(is_not_release)");
|
||||||
|
println!("cargo:rerun-if-env-changed=CI");
|
||||||
|
#[cfg(debug_assertions)]
|
||||||
|
if std::env::var("CI").is_err() {
|
||||||
|
println!("cargo::rustc-cfg=is_not_release");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -22,7 +22,7 @@ use esp_println::{print, println};
|
|||||||
|
|
||||||
const WIDTH: usize = 80;
|
const WIDTH: usize = 80;
|
||||||
|
|
||||||
#[cfg(debug_assertions)]
|
#[cfg(is_not_release)]
|
||||||
compile_error!("Run this example in release mode");
|
compile_error!("Run this example in release mode");
|
||||||
|
|
||||||
#[embassy_executor::task]
|
#[embassy_executor::task]
|
||||||
|
|||||||
@ -25,11 +25,11 @@ fn init_psram_heap() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(is_not_release)]
|
||||||
|
compile_error!("PSRAM example must be built in release mode!");
|
||||||
|
|
||||||
#[entry]
|
#[entry]
|
||||||
fn main() -> ! {
|
fn main() -> ! {
|
||||||
#[cfg(debug_assertions)]
|
|
||||||
compile_error!("This example MUST be built in release mode!");
|
|
||||||
|
|
||||||
let peripherals = esp_hal::init(esp_hal::Config::default());
|
let peripherals = esp_hal::init(esp_hal::Config::default());
|
||||||
|
|
||||||
psram::init_psram(peripherals.PSRAM);
|
psram::init_psram(peripherals.PSRAM);
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
//! This shows how to use PSRAM as heap-memory via esp-alloc
|
//! This shows how to use PSRAM as heap-memory via esp-alloc
|
||||||
//!
|
//!
|
||||||
//! You need an ESP32, ESP32-S2, or ESP32-S3 with at least 2 MB of PSRAM memory.
|
//! You need an ESP32, ESP32-S2 or ESP32-S3 with at least 2 MB of PSRAM memory.
|
||||||
|
|
||||||
//% CHIPS: esp32 esp32s2 esp32s3
|
//% CHIPS: esp32 esp32s2 esp32s3
|
||||||
//% FEATURES: psram-2m
|
//% FEATURES: psram-2m
|
||||||
@ -25,11 +25,11 @@ fn init_psram_heap() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(is_not_release)]
|
||||||
|
compile_error!("PSRAM example must be built in release mode!");
|
||||||
|
|
||||||
#[entry]
|
#[entry]
|
||||||
fn main() -> ! {
|
fn main() -> ! {
|
||||||
#[cfg(debug_assertions)]
|
|
||||||
compile_error!("PSRAM example must be built in release mode!");
|
|
||||||
|
|
||||||
let peripherals = esp_hal::init(esp_hal::Config::default());
|
let peripherals = esp_hal::init(esp_hal::Config::default());
|
||||||
|
|
||||||
psram::init_psram(peripherals.PSRAM);
|
psram::init_psram(peripherals.PSRAM);
|
||||||
|
|||||||
@ -113,6 +113,14 @@ impl CargoArgsBuilder {
|
|||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn add_arg<S>(&mut self, arg: S) -> &mut Self
|
||||||
|
where
|
||||||
|
S: Into<String>,
|
||||||
|
{
|
||||||
|
self.args.push(arg.into());
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub fn build(self) -> Vec<String> {
|
pub fn build(self) -> Vec<String> {
|
||||||
let mut args = vec![];
|
let mut args = vec![];
|
||||||
|
|||||||
@ -57,11 +57,11 @@ pub enum Package {
|
|||||||
pub struct Metadata {
|
pub struct Metadata {
|
||||||
example_path: PathBuf,
|
example_path: PathBuf,
|
||||||
chips: Vec<Chip>,
|
chips: Vec<Chip>,
|
||||||
feature_sets: Vec<Vec<String>>,
|
feature_set: Vec<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Metadata {
|
impl Metadata {
|
||||||
pub fn new(example_path: &Path, chips: Vec<Chip>, feature_sets: Vec<Vec<String>>) -> Self {
|
pub fn new(example_path: &Path, chips: Vec<Chip>, feature_set: Vec<String>) -> Self {
|
||||||
let chips = if chips.is_empty() {
|
let chips = if chips.is_empty() {
|
||||||
Chip::iter().collect()
|
Chip::iter().collect()
|
||||||
} else {
|
} else {
|
||||||
@ -71,7 +71,7 @@ impl Metadata {
|
|||||||
Self {
|
Self {
|
||||||
example_path: example_path.to_path_buf(),
|
example_path: example_path.to_path_buf(),
|
||||||
chips,
|
chips,
|
||||||
feature_sets,
|
feature_set,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -89,9 +89,9 @@ impl Metadata {
|
|||||||
.replace(".rs", "")
|
.replace(".rs", "")
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A list of all features required for building a given examples.
|
/// A list of all features required for building a given example.
|
||||||
pub fn feature_sets(&self) -> &[Vec<String>] {
|
pub fn feature_set(&self) -> &[String] {
|
||||||
&self.feature_sets
|
&self.feature_set
|
||||||
}
|
}
|
||||||
|
|
||||||
/// If the specified chip is in the list of chips, then it is supported.
|
/// If the specified chip is in the list of chips, then it is supported.
|
||||||
@ -154,7 +154,7 @@ pub fn build_documentation(
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Load all examples at the given path, and parse their metadata.
|
/// Load all examples at the given path, and parse their metadata.
|
||||||
pub fn load_examples(path: &Path) -> Result<Vec<Metadata>> {
|
pub fn load_examples(path: &Path, action: CargoAction) -> Result<Vec<Metadata>> {
|
||||||
let mut examples = Vec::new();
|
let mut examples = Vec::new();
|
||||||
|
|
||||||
for entry in fs::read_dir(path)? {
|
for entry in fs::read_dir(path)? {
|
||||||
@ -172,7 +172,7 @@ pub fn load_examples(path: &Path) -> Result<Vec<Metadata>> {
|
|||||||
.trim()
|
.trim()
|
||||||
.split_ascii_whitespace()
|
.split_ascii_whitespace()
|
||||||
.map(|s| s.to_string())
|
.map(|s| s.to_string())
|
||||||
.collect::<VecDeque<_>>();
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
if split.len() < 2 {
|
if split.len() < 2 {
|
||||||
bail!(
|
bail!(
|
||||||
@ -182,7 +182,7 @@ pub fn load_examples(path: &Path) -> Result<Vec<Metadata>> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// The trailing ':' on metadata keys is optional :)
|
// The trailing ':' on metadata keys is optional :)
|
||||||
let key = split.pop_front().unwrap();
|
let key = split.swap_remove(0);
|
||||||
let key = key.trim_end_matches(':');
|
let key = key.trim_end_matches(':');
|
||||||
|
|
||||||
if key == "CHIPS" {
|
if key == "CHIPS" {
|
||||||
@ -191,15 +191,31 @@ pub fn load_examples(path: &Path) -> Result<Vec<Metadata>> {
|
|||||||
.map(|s| Chip::from_str(s, false).unwrap())
|
.map(|s| Chip::from_str(s, false).unwrap())
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
} else if key == "FEATURES" {
|
} else if key == "FEATURES" {
|
||||||
feature_sets.push(split.into());
|
// Sort the features so they are in a deterministic order:
|
||||||
|
split.sort();
|
||||||
|
feature_sets.push(split);
|
||||||
} else {
|
} else {
|
||||||
log::warn!("Unrecognized metadata key '{key}', ignoring");
|
log::warn!("Unrecognized metadata key '{key}', ignoring");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
examples.push(Metadata::new(&path, chips, feature_sets));
|
if feature_sets.is_empty() {
|
||||||
|
feature_sets.push(Vec::new());
|
||||||
|
}
|
||||||
|
if action == CargoAction::Build {
|
||||||
|
// Only build the first feature set for each example.
|
||||||
|
// Rebuilding with a different feature set just wastes time because the latter
|
||||||
|
// one will overwrite the former one(s).
|
||||||
|
feature_sets.truncate(1);
|
||||||
|
}
|
||||||
|
for feature_set in feature_sets {
|
||||||
|
examples.push(Metadata::new(&path, chips.clone(), feature_set));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Sort by feature set, to prevent rebuilding packages if not necessary.
|
||||||
|
examples.sort_by_key(|e| e.feature_set().join(","));
|
||||||
|
|
||||||
Ok(examples)
|
Ok(examples)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -210,7 +226,8 @@ pub fn execute_app(
|
|||||||
target: &str,
|
target: &str,
|
||||||
app: &Metadata,
|
app: &Metadata,
|
||||||
action: CargoAction,
|
action: CargoAction,
|
||||||
repeat: usize,
|
mut repeat: usize,
|
||||||
|
debug: bool,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
log::info!(
|
log::info!(
|
||||||
"Building example '{}' for '{}'",
|
"Building example '{}' for '{}'",
|
||||||
@ -218,30 +235,7 @@ pub fn execute_app(
|
|||||||
chip
|
chip
|
||||||
);
|
);
|
||||||
|
|
||||||
let feature_sets = if app.feature_sets().is_empty() {
|
let mut features = app.feature_set().to_vec();
|
||||||
vec![vec![]]
|
|
||||||
} else {
|
|
||||||
app.feature_sets().to_vec()
|
|
||||||
};
|
|
||||||
|
|
||||||
for features in feature_sets {
|
|
||||||
execute_app_with_features(package_path, chip, target, app, action, repeat, features)?;
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Run or build the specified test or example for the specified chip, with the
|
|
||||||
/// specified features enabled.
|
|
||||||
pub fn execute_app_with_features(
|
|
||||||
package_path: &Path,
|
|
||||||
chip: Chip,
|
|
||||||
target: &str,
|
|
||||||
app: &Metadata,
|
|
||||||
action: CargoAction,
|
|
||||||
mut repeat: usize,
|
|
||||||
mut features: Vec<String>,
|
|
||||||
) -> Result<()> {
|
|
||||||
if !features.is_empty() {
|
if !features.is_empty() {
|
||||||
log::info!("Features: {}", features.join(","));
|
log::info!("Features: {}", features.join(","));
|
||||||
}
|
}
|
||||||
@ -269,19 +263,22 @@ pub fn execute_app_with_features(
|
|||||||
|
|
||||||
let mut builder = CargoArgsBuilder::default()
|
let mut builder = CargoArgsBuilder::default()
|
||||||
.subcommand(subcommand)
|
.subcommand(subcommand)
|
||||||
.arg("--release")
|
|
||||||
.target(target)
|
.target(target)
|
||||||
.features(&features)
|
.features(&features)
|
||||||
.arg(bin);
|
.arg(bin);
|
||||||
|
|
||||||
|
if !debug {
|
||||||
|
builder.add_arg("--release");
|
||||||
|
}
|
||||||
|
|
||||||
if subcommand == "test" && chip == Chip::Esp32c2 {
|
if subcommand == "test" && chip == Chip::Esp32c2 {
|
||||||
builder = builder.arg("--").arg("--speed").arg("15000");
|
builder.add_arg("--").add_arg("--speed").add_arg("15000");
|
||||||
}
|
}
|
||||||
|
|
||||||
// If targeting an Xtensa device, we must use the '+esp' toolchain modifier:
|
// If targeting an Xtensa device, we must use the '+esp' toolchain modifier:
|
||||||
if target.starts_with("xtensa") {
|
if target.starts_with("xtensa") {
|
||||||
builder = builder.toolchain("esp");
|
builder = builder.toolchain("esp");
|
||||||
builder = builder.arg("-Zbuild-std=core,alloc")
|
builder.add_arg("-Zbuild-std=core,alloc");
|
||||||
}
|
}
|
||||||
|
|
||||||
let args = builder.build();
|
let args = builder.build();
|
||||||
|
|||||||
@ -58,6 +58,9 @@ struct ExampleArgs {
|
|||||||
chip: Chip,
|
chip: Chip,
|
||||||
/// Optional example to act on (all examples used if omitted)
|
/// Optional example to act on (all examples used if omitted)
|
||||||
example: Option<String>,
|
example: Option<String>,
|
||||||
|
/// Build examples in debug mode only
|
||||||
|
#[arg(long)]
|
||||||
|
debug: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Args)]
|
#[derive(Debug, Args)]
|
||||||
@ -202,7 +205,7 @@ fn examples(workspace: &Path, mut args: ExampleArgs, action: CargoAction) -> Res
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Load all examples which support the specified chip and parse their metadata:
|
// Load all examples which support the specified chip and parse their metadata:
|
||||||
let mut examples = xtask::load_examples(&example_path)?
|
let mut examples = xtask::load_examples(&example_path, action)?
|
||||||
.iter()
|
.iter()
|
||||||
.filter_map(|example| {
|
.filter_map(|example| {
|
||||||
if example.supports_chip(args.chip) {
|
if example.supports_chip(args.chip) {
|
||||||
@ -227,16 +230,24 @@ fn build_examples(args: ExampleArgs, examples: Vec<Metadata>, package_path: &Pat
|
|||||||
// Determine the appropriate build target for the given package and chip:
|
// Determine the appropriate build target for the given package and chip:
|
||||||
let target = target_triple(args.package, &args.chip)?;
|
let target = target_triple(args.package, &args.chip)?;
|
||||||
|
|
||||||
if let Some(example) = examples.iter().find(|ex| Some(ex.name()) == args.example) {
|
if examples
|
||||||
|
.iter()
|
||||||
|
.find(|ex| Some(ex.name()) == args.example)
|
||||||
|
.is_some()
|
||||||
|
{
|
||||||
// Attempt to build only the specified example:
|
// Attempt to build only the specified example:
|
||||||
xtask::execute_app(
|
for example in examples.iter().filter(|ex| Some(ex.name()) == args.example) {
|
||||||
package_path,
|
xtask::execute_app(
|
||||||
args.chip,
|
package_path,
|
||||||
target,
|
args.chip,
|
||||||
example,
|
target,
|
||||||
CargoAction::Build,
|
example,
|
||||||
1,
|
CargoAction::Build,
|
||||||
)
|
1,
|
||||||
|
args.debug,
|
||||||
|
)?;
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
} else if args.example.is_some() {
|
} else if args.example.is_some() {
|
||||||
// An invalid argument was provided:
|
// An invalid argument was provided:
|
||||||
bail!("Example not found or unsupported for the given chip")
|
bail!("Example not found or unsupported for the given chip")
|
||||||
@ -250,6 +261,7 @@ fn build_examples(args: ExampleArgs, examples: Vec<Metadata>, package_path: &Pat
|
|||||||
example,
|
example,
|
||||||
CargoAction::Build,
|
CargoAction::Build,
|
||||||
1,
|
1,
|
||||||
|
args.debug,
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -261,7 +273,9 @@ fn run_example(args: ExampleArgs, examples: Vec<Metadata>, package_path: &Path)
|
|||||||
|
|
||||||
// Filter the examples down to only the binary we're interested in, assuming it
|
// Filter the examples down to only the binary we're interested in, assuming it
|
||||||
// actually supports the specified chip:
|
// actually supports the specified chip:
|
||||||
if let Some(example) = examples.iter().find(|ex| Some(ex.name()) == args.example) {
|
let mut found_one = false;
|
||||||
|
for example in examples.iter().filter(|ex| Some(ex.name()) == args.example) {
|
||||||
|
found_one = true;
|
||||||
xtask::execute_app(
|
xtask::execute_app(
|
||||||
package_path,
|
package_path,
|
||||||
args.chip,
|
args.chip,
|
||||||
@ -269,10 +283,17 @@ fn run_example(args: ExampleArgs, examples: Vec<Metadata>, package_path: &Path)
|
|||||||
example,
|
example,
|
||||||
CargoAction::Run,
|
CargoAction::Run,
|
||||||
1,
|
1,
|
||||||
)
|
args.debug,
|
||||||
} else {
|
)?;
|
||||||
bail!("Example not found or unsupported for the given chip")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ensure!(
|
||||||
|
found_one,
|
||||||
|
"Example not found or unsupported for {}",
|
||||||
|
args.chip
|
||||||
|
);
|
||||||
|
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn tests(workspace: &Path, args: TestArgs, action: CargoAction) -> Result<()> {
|
fn tests(workspace: &Path, args: TestArgs, action: CargoAction) -> Result<()> {
|
||||||
@ -283,7 +304,7 @@ fn tests(workspace: &Path, args: TestArgs, action: CargoAction) -> Result<()> {
|
|||||||
let target = target_triple(Package::HilTest, &args.chip)?;
|
let target = target_triple(Package::HilTest, &args.chip)?;
|
||||||
|
|
||||||
// Load all tests which support the specified chip and parse their metadata:
|
// Load all tests which support the specified chip and parse their metadata:
|
||||||
let mut tests = xtask::load_examples(&package_path.join("tests"))?
|
let mut tests = xtask::load_examples(&package_path.join("tests"), action)?
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.filter(|example| example.supports_chip(args.chip))
|
.filter(|example| example.supports_chip(args.chip))
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
@ -292,15 +313,23 @@ fn tests(workspace: &Path, args: TestArgs, action: CargoAction) -> Result<()> {
|
|||||||
tests.sort_by_key(|a| a.name());
|
tests.sort_by_key(|a| a.name());
|
||||||
|
|
||||||
// Execute the specified action:
|
// Execute the specified action:
|
||||||
if let Some(test) = tests.iter().find(|test| Some(test.name()) == args.test) {
|
if tests
|
||||||
xtask::execute_app(
|
.iter()
|
||||||
&package_path,
|
.find(|test| Some(test.name()) == args.test)
|
||||||
args.chip,
|
.is_some()
|
||||||
target,
|
{
|
||||||
test,
|
for test in tests.iter().filter(|test| Some(test.name()) == args.test) {
|
||||||
action,
|
xtask::execute_app(
|
||||||
args.repeat.unwrap_or(1),
|
&package_path,
|
||||||
)
|
args.chip,
|
||||||
|
target,
|
||||||
|
test,
|
||||||
|
action,
|
||||||
|
args.repeat.unwrap_or(1),
|
||||||
|
false,
|
||||||
|
)?;
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
} else if args.test.is_some() {
|
} else if args.test.is_some() {
|
||||||
bail!("Test not found or unsupported for the given chip")
|
bail!("Test not found or unsupported for the given chip")
|
||||||
} else {
|
} else {
|
||||||
@ -313,6 +342,7 @@ fn tests(workspace: &Path, args: TestArgs, action: CargoAction) -> Result<()> {
|
|||||||
&test,
|
&test,
|
||||||
action,
|
action,
|
||||||
args.repeat.unwrap_or(1),
|
args.repeat.unwrap_or(1),
|
||||||
|
false,
|
||||||
)
|
)
|
||||||
.is_err()
|
.is_err()
|
||||||
{
|
{
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user