Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Build examples in debug mode #2078

Merged
merged 3 commits into from
Sep 5, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion .github/actions/check-esp-hal/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -57,5 +57,7 @@ runs:
--target=${{ inputs.target }} \
esp-hal
- name: Build (examples)
env:
CI: 1
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
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,7 @@ jobs:
cargo xtask build-package --features=esp32c3,wifi,ble,async --target=riscv32imc-unknown-none-elf esp-wifi
cargo xtask build-package --features=esp32c6,wifi,ble,async --target=riscv32imac-unknown-none-elf esp-wifi
cargo xtask build-package --features=esp32h2,ble,async --target=riscv32imac-unknown-none-elf esp-wifi

# Verify the MSRV for all Xtensa chips:
- name: msrv Xtensa (esp-hal)
run: |
Expand Down
4 changes: 2 additions & 2 deletions esp-storage/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,14 @@ fn main() -> Result<(), String> {

if cfg!(feature = "esp32") {
match std::env::var("OPT_LEVEL") {
Ok(level) => {
Ok(level) if std::env::var("CI").is_err() => {
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))
} else {
Ok(())
}
}
Err(_err) => Ok(()),
_ => Ok(()),
}
} else {
Ok(())
Expand Down
8 changes: 8 additions & 0 deletions examples/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,12 @@ fn main() {
if cfg!(feature = "esp-wifi") {
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");
}
}
2 changes: 1 addition & 1 deletion examples/src/bin/embassy_rmt_rx.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ use esp_println::{print, println};

const WIDTH: usize = 80;

#[cfg(debug_assertions)]
#[cfg(is_not_release)]
compile_error!("Run this example in release mode");

#[embassy_executor::task]
Expand Down
6 changes: 3 additions & 3 deletions examples/src/bin/psram_octal.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,11 @@ fn init_psram_heap() {
}
}

#[cfg(is_not_release)]
compile_error!("PSRAM example must be built in release mode!");

#[entry]
fn main() -> ! {
#[cfg(debug_assertions)]
compile_error!("This example MUST be built in release mode!");

let peripherals = esp_hal::init(esp_hal::Config::default());

psram::init_psram(peripherals.PSRAM);
Expand Down
8 changes: 4 additions & 4 deletions examples/src/bin/psram_quad.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
//! 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
//% FEATURES: psram-2m
Expand All @@ -25,11 +25,11 @@ fn init_psram_heap() {
}
}

#[cfg(is_not_release)]
compile_error!("PSRAM example must be built in release mode!");

#[entry]
fn main() -> ! {
#[cfg(debug_assertions)]
compile_error!("PSRAM example must be built in release mode!");

let peripherals = esp_hal::init(esp_hal::Config::default());

psram::init_psram(peripherals.PSRAM);
Expand Down
8 changes: 8 additions & 0 deletions xtask/src/cargo.rs
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,14 @@ impl CargoArgsBuilder {
self
}

pub fn add_arg<S>(&mut self, arg: S) -> &mut Self
where
S: Into<String>,
{
self.args.push(arg.into());
self
}

#[must_use]
pub fn build(self) -> Vec<String> {
let mut args = vec![];
Expand Down
75 changes: 36 additions & 39 deletions xtask/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -57,11 +57,11 @@ pub enum Package {
pub struct Metadata {
example_path: PathBuf,
chips: Vec<Chip>,
feature_sets: Vec<Vec<String>>,
feature_set: Vec<String>,
}

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() {
Chip::iter().collect()
} else {
Expand All @@ -71,7 +71,7 @@ impl Metadata {
Self {
example_path: example_path.to_path_buf(),
chips,
feature_sets,
feature_set,
}
}

Expand All @@ -89,9 +89,9 @@ impl Metadata {
.replace(".rs", "")
}

/// A list of all features required for building a given examples.
pub fn feature_sets(&self) -> &[Vec<String>] {
&self.feature_sets
/// A list of all features required for building a given example.
pub fn feature_set(&self) -> &[String] {
&self.feature_set
}

/// If the specified chip is in the list of chips, then it is supported.
Expand Down Expand Up @@ -154,7 +154,7 @@ pub fn build_documentation(
}

/// 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();

for entry in fs::read_dir(path)? {
Expand All @@ -172,7 +172,7 @@ pub fn load_examples(path: &Path) -> Result<Vec<Metadata>> {
.trim()
.split_ascii_whitespace()
.map(|s| s.to_string())
.collect::<VecDeque<_>>();
.collect::<Vec<_>>();

if split.len() < 2 {
bail!(
Expand All @@ -182,7 +182,7 @@ pub fn load_examples(path: &Path) -> Result<Vec<Metadata>> {
}

// 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(':');

if key == "CHIPS" {
Expand All @@ -191,15 +191,31 @@ pub fn load_examples(path: &Path) -> Result<Vec<Metadata>> {
.map(|s| Chip::from_str(s, false).unwrap())
.collect::<Vec<_>>();
} 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 {
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)
}

Expand All @@ -210,38 +226,16 @@ pub fn execute_app(
target: &str,
app: &Metadata,
action: CargoAction,
repeat: usize,
mut repeat: usize,
debug: bool,
) -> Result<()> {
log::info!(
"Building example '{}' for '{}'",
app.example_path().display(),
chip
);

let feature_sets = if app.feature_sets().is_empty() {
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<()> {
let mut features = app.feature_set().to_vec();
if !features.is_empty() {
log::info!("Features: {}", features.join(","));
}
Expand Down Expand Up @@ -269,19 +263,22 @@ pub fn execute_app_with_features(

let mut builder = CargoArgsBuilder::default()
.subcommand(subcommand)
.arg("--release")
.target(target)
.features(&features)
.arg(bin);

if !debug {
builder.add_arg("--release");
}

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 target.starts_with("xtensa") {
builder = builder.toolchain("esp");
builder = builder.arg("-Zbuild-std=core,alloc")
builder.add_arg("-Zbuild-std=core,alloc");
}

let args = builder.build();
Expand Down
Loading