Skip to content

Commit 5370afb

Browse files
authored
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
1 parent 42a0417 commit 5370afb

File tree

10 files changed

+120
-75
lines changed

10 files changed

+120
-75
lines changed

.github/actions/check-esp-hal/action.yml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,5 +57,7 @@ runs:
5757
--target=${{ inputs.target }} \
5858
esp-hal
5959
- name: Build (examples)
60+
env:
61+
CI: 1
6062
shell: bash
61-
run: cargo +${{ inputs.toolchain }} xtask build-examples esp-hal ${{ inputs.device }}
63+
run: cargo +${{ inputs.toolchain }} xtask build-examples esp-hal ${{ inputs.device }} --debug

.github/workflows/ci.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -140,7 +140,7 @@ jobs:
140140
cargo xtask build-package --features=esp32c3,wifi,ble,async --target=riscv32imc-unknown-none-elf esp-wifi
141141
cargo xtask build-package --features=esp32c6,wifi,ble,async --target=riscv32imac-unknown-none-elf esp-wifi
142142
cargo xtask build-package --features=esp32h2,ble,async --target=riscv32imac-unknown-none-elf esp-wifi
143-
143+
144144
# Verify the MSRV for all Xtensa chips:
145145
- name: msrv Xtensa (esp-hal)
146146
run: |

esp-storage/build.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,14 @@ fn main() -> Result<(), String> {
66

77
if cfg!(feature = "esp32") {
88
match std::env::var("OPT_LEVEL") {
9-
Ok(level) => {
9+
Ok(level) if std::env::var("CI").is_err() => {
1010
if level != "2" && level != "3" {
1111
Err(format!("Building esp-storage for ESP32 needs optimization level 2 or 3 - yours is {}. See https://github.com/esp-rs/esp-storage", level))
1212
} else {
1313
Ok(())
1414
}
1515
}
16-
Err(_err) => Ok(()),
16+
_ => Ok(()),
1717
}
1818
} else {
1919
Ok(())

examples/build.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,4 +8,12 @@ fn main() {
88
if cfg!(feature = "esp-wifi") {
99
println!("cargo::rustc-link-arg=-Trom_functions.x");
1010
}
11+
12+
// Allow building examples in CI in debug mode
13+
println!("cargo:rustc-check-cfg=cfg(is_not_release)");
14+
println!("cargo:rerun-if-env-changed=CI");
15+
#[cfg(debug_assertions)]
16+
if std::env::var("CI").is_err() {
17+
println!("cargo::rustc-cfg=is_not_release");
18+
}
1119
}

examples/src/bin/embassy_rmt_rx.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ use esp_println::{print, println};
2222

2323
const WIDTH: usize = 80;
2424

25-
#[cfg(debug_assertions)]
25+
#[cfg(is_not_release)]
2626
compile_error!("Run this example in release mode");
2727

2828
#[embassy_executor::task]

examples/src/bin/psram_octal.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,11 +25,11 @@ fn init_psram_heap() {
2525
}
2626
}
2727

28+
#[cfg(is_not_release)]
29+
compile_error!("PSRAM example must be built in release mode!");
30+
2831
#[entry]
2932
fn main() -> ! {
30-
#[cfg(debug_assertions)]
31-
compile_error!("This example MUST be built in release mode!");
32-
3333
let peripherals = esp_hal::init(esp_hal::Config::default());
3434

3535
psram::init_psram(peripherals.PSRAM);

examples/src/bin/psram_quad.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
//! This shows how to use PSRAM as heap-memory via esp-alloc
22
//!
3-
//! You need an ESP32, ESP32-S2, or ESP32-S3 with at least 2 MB of PSRAM memory.
3+
//! You need an ESP32, ESP32-S2 or ESP32-S3 with at least 2 MB of PSRAM memory.
44
55
//% CHIPS: esp32 esp32s2 esp32s3
66
//% FEATURES: psram-2m
@@ -25,11 +25,11 @@ fn init_psram_heap() {
2525
}
2626
}
2727

28+
#[cfg(is_not_release)]
29+
compile_error!("PSRAM example must be built in release mode!");
30+
2831
#[entry]
2932
fn main() -> ! {
30-
#[cfg(debug_assertions)]
31-
compile_error!("PSRAM example must be built in release mode!");
32-
3333
let peripherals = esp_hal::init(esp_hal::Config::default());
3434

3535
psram::init_psram(peripherals.PSRAM);

xtask/src/cargo.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,14 @@ impl CargoArgsBuilder {
113113
self
114114
}
115115

116+
pub fn add_arg<S>(&mut self, arg: S) -> &mut Self
117+
where
118+
S: Into<String>,
119+
{
120+
self.args.push(arg.into());
121+
self
122+
}
123+
116124
#[must_use]
117125
pub fn build(self) -> Vec<String> {
118126
let mut args = vec![];

xtask/src/lib.rs

Lines changed: 36 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -57,11 +57,11 @@ pub enum Package {
5757
pub struct Metadata {
5858
example_path: PathBuf,
5959
chips: Vec<Chip>,
60-
feature_sets: Vec<Vec<String>>,
60+
feature_set: Vec<String>,
6161
}
6262

6363
impl Metadata {
64-
pub fn new(example_path: &Path, chips: Vec<Chip>, feature_sets: Vec<Vec<String>>) -> Self {
64+
pub fn new(example_path: &Path, chips: Vec<Chip>, feature_set: Vec<String>) -> Self {
6565
let chips = if chips.is_empty() {
6666
Chip::iter().collect()
6767
} else {
@@ -71,7 +71,7 @@ impl Metadata {
7171
Self {
7272
example_path: example_path.to_path_buf(),
7373
chips,
74-
feature_sets,
74+
feature_set,
7575
}
7676
}
7777

@@ -89,9 +89,9 @@ impl Metadata {
8989
.replace(".rs", "")
9090
}
9191

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

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

156156
/// Load all examples at the given path, and parse their metadata.
157-
pub fn load_examples(path: &Path) -> Result<Vec<Metadata>> {
157+
pub fn load_examples(path: &Path, action: CargoAction) -> Result<Vec<Metadata>> {
158158
let mut examples = Vec::new();
159159

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

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

184184
// The trailing ':' on metadata keys is optional :)
185-
let key = split.pop_front().unwrap();
185+
let key = split.swap_remove(0);
186186
let key = key.trim_end_matches(':');
187187

188188
if key == "CHIPS" {
@@ -191,15 +191,31 @@ pub fn load_examples(path: &Path) -> Result<Vec<Metadata>> {
191191
.map(|s| Chip::from_str(s, false).unwrap())
192192
.collect::<Vec<_>>();
193193
} else if key == "FEATURES" {
194-
feature_sets.push(split.into());
194+
// Sort the features so they are in a deterministic order:
195+
split.sort();
196+
feature_sets.push(split);
195197
} else {
196198
log::warn!("Unrecognized metadata key '{key}', ignoring");
197199
}
198200
}
199201

200-
examples.push(Metadata::new(&path, chips, feature_sets));
202+
if feature_sets.is_empty() {
203+
feature_sets.push(Vec::new());
204+
}
205+
if action == CargoAction::Build {
206+
// Only build the first feature set for each example.
207+
// Rebuilding with a different feature set just wastes time because the latter
208+
// one will overwrite the former one(s).
209+
feature_sets.truncate(1);
210+
}
211+
for feature_set in feature_sets {
212+
examples.push(Metadata::new(&path, chips.clone(), feature_set));
213+
}
201214
}
202215

216+
// Sort by feature set, to prevent rebuilding packages if not necessary.
217+
examples.sort_by_key(|e| e.feature_set().join(","));
218+
203219
Ok(examples)
204220
}
205221

@@ -210,38 +226,16 @@ pub fn execute_app(
210226
target: &str,
211227
app: &Metadata,
212228
action: CargoAction,
213-
repeat: usize,
229+
mut repeat: usize,
230+
debug: bool,
214231
) -> Result<()> {
215232
log::info!(
216233
"Building example '{}' for '{}'",
217234
app.example_path().display(),
218235
chip
219236
);
220237

221-
let feature_sets = if app.feature_sets().is_empty() {
222-
vec![vec![]]
223-
} else {
224-
app.feature_sets().to_vec()
225-
};
226-
227-
for features in feature_sets {
228-
execute_app_with_features(package_path, chip, target, app, action, repeat, features)?;
229-
}
230-
231-
Ok(())
232-
}
233-
234-
/// Run or build the specified test or example for the specified chip, with the
235-
/// specified features enabled.
236-
pub fn execute_app_with_features(
237-
package_path: &Path,
238-
chip: Chip,
239-
target: &str,
240-
app: &Metadata,
241-
action: CargoAction,
242-
mut repeat: usize,
243-
mut features: Vec<String>,
244-
) -> Result<()> {
238+
let mut features = app.feature_set().to_vec();
245239
if !features.is_empty() {
246240
log::info!("Features: {}", features.join(","));
247241
}
@@ -269,19 +263,22 @@ pub fn execute_app_with_features(
269263

270264
let mut builder = CargoArgsBuilder::default()
271265
.subcommand(subcommand)
272-
.arg("--release")
273266
.target(target)
274267
.features(&features)
275268
.arg(bin);
276269

270+
if !debug {
271+
builder.add_arg("--release");
272+
}
273+
277274
if subcommand == "test" && chip == Chip::Esp32c2 {
278-
builder = builder.arg("--").arg("--speed").arg("15000");
275+
builder.add_arg("--").add_arg("--speed").add_arg("15000");
279276
}
280277

281278
// If targeting an Xtensa device, we must use the '+esp' toolchain modifier:
282279
if target.starts_with("xtensa") {
283280
builder = builder.toolchain("esp");
284-
builder = builder.arg("-Zbuild-std=core,alloc")
281+
builder.add_arg("-Zbuild-std=core,alloc");
285282
}
286283

287284
let args = builder.build();

0 commit comments

Comments
 (0)