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

Add chip-specific features for tests/examples #2175

Merged
merged 3 commits into from
Sep 23, 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
1 change: 1 addition & 0 deletions esp-metadata/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ pub enum Cores {
Eq,
PartialOrd,
Ord,
Hash,
serde::Deserialize,
serde::Serialize,
strum::Display,
Expand Down
90 changes: 56 additions & 34 deletions xtask/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use std::{
collections::VecDeque,
collections::{HashMap, VecDeque},
fs::{self, File},
io::Write as _,
path::{Path, PathBuf},
Expand Down Expand Up @@ -52,24 +52,18 @@ pub enum Package {
XtensaLxRt,
}

#[derive(Debug, Default, Clone)]
#[derive(Debug, Clone)]
pub struct Metadata {
example_path: PathBuf,
chips: Vec<Chip>,
chip: Chip,
feature_set: Vec<String>,
}

impl Metadata {
pub fn new(example_path: &Path, chips: Vec<Chip>, feature_set: Vec<String>) -> Self {
let chips = if chips.is_empty() {
Chip::iter().collect()
} else {
chips
};

pub fn new(example_path: &Path, chip: Chip, feature_set: Vec<String>) -> Self {
Self {
example_path: example_path.to_path_buf(),
chips,
chip,
feature_set,
}
}
Expand All @@ -95,7 +89,7 @@ impl Metadata {

/// If the specified chip is in the list of chips, then it is supported.
pub fn supports_chip(&self, chip: Chip) -> bool {
self.chips.contains(&chip)
self.chip == chip
}
}

Expand Down Expand Up @@ -161,38 +155,56 @@ pub fn load_examples(path: &Path, action: CargoAction) -> Result<Vec<Metadata>>
let text = fs::read_to_string(&path)
.with_context(|| format!("Could not read {}", path.display()))?;

let mut chips = Vec::new();
let mut chips = Chip::iter().collect::<Vec<_>>();
let mut feature_sets = Vec::new();
let mut chip_features = HashMap::new();

// We will indicate metadata lines using the `//%` prefix:
for line in text.lines().filter(|line| line.starts_with("//%")) {
let mut split = line
.trim_start_matches("//%")
.trim()
.split_ascii_whitespace()
.map(|s| s.to_string())
.collect::<Vec<_>>();

if split.len() < 2 {
bail!(
"Expected at least two elements (key, value), found {}",
split.len()
);
}
let Some((key, value)) = line.trim_start_matches("//%").split_once(':') else {
bail!("Metadata line is missing ':': {}", line);
};

// The trailing ':' on metadata keys is optional :)
Copy link
Contributor

@bjoernQ bjoernQ Sep 19, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

technically a change but given I didn't even know this I guess that is totally fine

let key = split.swap_remove(0);
let key = key.trim_end_matches(':');
let key = key.trim();

if key == "CHIPS" {
chips = split
.iter()
chips = value
.split_ascii_whitespace()
.map(|s| Chip::from_str(s, false).unwrap())
.collect::<Vec<_>>();
} else if key == "FEATURES" {
// Base feature set required to run the example.
// If multiple are specified, we compile the same example multiple times.
let mut values = value
.split_ascii_whitespace()
.map(ToString::to_string)
.collect::<Vec<_>>();

// Sort the features so they are in a deterministic order:
split.sort();
feature_sets.push(split);
values.sort();

feature_sets.push(values);
} else if key.starts_with("CHIP-FEATURES(") {
// Additional features required for specific chips.
// These are appended to the base feature set(s).
// If multiple are specified, the last entry wins.
let chips = key
.trim_start_matches("CHIP-FEATURES(")
.trim_end_matches(')');

let chips = chips
.split_ascii_whitespace()
.map(|s| Chip::from_str(s, false).unwrap())
.collect::<Vec<_>>();

let values = value
.split_ascii_whitespace()
.map(ToString::to_string)
.collect::<Vec<_>>();

for chip in chips {
chip_features.insert(chip, values.clone());
}
} else {
log::warn!("Unrecognized metadata key '{key}', ignoring");
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

unrelated but we might consider to make this an hard error and panic - took we a while to recognize I was testing with CHIP_FEATURE(esp32s3) 😄

}
Expand All @@ -208,7 +220,17 @@ pub fn load_examples(path: &Path, action: CargoAction) -> Result<Vec<Metadata>>
feature_sets.truncate(1);
}
for feature_set in feature_sets {
examples.push(Metadata::new(&path, chips.clone(), feature_set));
for chip in &chips {
let mut feature_set = feature_set.clone();
if let Some(chip_features) = chip_features.get(chip) {
feature_set.extend(chip_features.iter().cloned());

// Sort the features so they are in a deterministic order:
feature_set.sort();
}

examples.push(Metadata::new(&path, *chip, feature_set.clone()));
}
}
}

Expand Down