From 6c7b7183d13b1a1a0d5d072555ac03c3a8bb8011 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?D=C3=A1niel=20Buga?= Date: Tue, 17 Sep 2024 09:38:30 +0200 Subject: [PATCH 1/3] Refactor metadata parsing to allow spaces in keys --- xtask/src/lib.rs | 50 ++++++++++++++++++++---------------------------- 1 file changed, 21 insertions(+), 29 deletions(-) diff --git a/xtask/src/lib.rs b/xtask/src/lib.rs index ae8a397bac8..0292f17ff0c 100644 --- a/xtask/src/lib.rs +++ b/xtask/src/lib.rs @@ -166,35 +166,27 @@ pub fn load_examples(path: &Path, action: CargoAction) -> Result> // 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::>(); - - if split.len() < 2 { - bail!( - "Expected at least two elements (key, value), found {}", - split.len() - ); - } - - // The trailing ':' on metadata keys is optional :) - let key = split.swap_remove(0); - let key = key.trim_end_matches(':'); - - if key == "CHIPS" { - chips = split - .iter() - .map(|s| Chip::from_str(s, false).unwrap()) - .collect::>(); - } else if key == "FEATURES" { - // Sort the features so they are in a deterministic order: - split.sort(); - feature_sets.push(split); - } else { - log::warn!("Unrecognized metadata key '{key}', ignoring"); + let Some((key, value)) = line.trim_start_matches("//%").split_once(':') else { + bail!("Metadata line is missing ':': {}", line); + }; + + match key.trim() { + "CHIPS" => { + chips = value + .split_ascii_whitespace() + .map(|s| Chip::from_str(s, false).unwrap()) + .collect::>(); + } + "FEATURES" => { + let mut values = value + .split_ascii_whitespace() + .map(ToString::to_string) + .collect::>(); + // Sort the features so they are in a deterministic order: + values.sort(); + feature_sets.push(values); + } + other => log::warn!("Unrecognized metadata key '{other}', ignoring"), } } From d7c8927bad98ca7562307a45f794c3aae7385d1b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?D=C3=A1niel=20Buga?= Date: Tue, 17 Sep 2024 09:51:25 +0200 Subject: [PATCH 2/3] Emit separate examples per chip --- xtask/src/lib.rs | 22 +++++++++------------- 1 file changed, 9 insertions(+), 13 deletions(-) diff --git a/xtask/src/lib.rs b/xtask/src/lib.rs index 0292f17ff0c..edc47577a28 100644 --- a/xtask/src/lib.rs +++ b/xtask/src/lib.rs @@ -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, feature_set: Vec, } impl Metadata { - pub fn new(example_path: &Path, chips: Vec, feature_set: Vec) -> Self { - let chips = if chips.is_empty() { - Chip::iter().collect() - } else { - chips - }; - + pub fn new(example_path: &Path, chip: Chip, feature_set: Vec) -> Self { Self { example_path: example_path.to_path_buf(), - chips, + chip, feature_set, } } @@ -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 } } @@ -161,7 +155,7 @@ pub fn load_examples(path: &Path, action: CargoAction) -> Result> 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::>(); let mut feature_sets = Vec::new(); // We will indicate metadata lines using the `//%` prefix: @@ -200,7 +194,9 @@ pub fn load_examples(path: &Path, action: CargoAction) -> Result> feature_sets.truncate(1); } for feature_set in feature_sets { - examples.push(Metadata::new(&path, chips.clone(), feature_set)); + for chip in &chips { + examples.push(Metadata::new(&path, *chip, feature_set.clone())); + } } } From 7cc8af5727d9062e7ce183b70e8d19ca0cd16cc8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?D=C3=A1niel=20Buga?= Date: Tue, 17 Sep 2024 10:00:05 +0200 Subject: [PATCH 3/3] Allow setting features for specific chips --- esp-metadata/src/lib.rs | 1 + xtask/src/lib.rs | 68 ++++++++++++++++++++++++++++++----------- 2 files changed, 52 insertions(+), 17 deletions(-) diff --git a/esp-metadata/src/lib.rs b/esp-metadata/src/lib.rs index 0f7ad939533..891bfa9038d 100644 --- a/esp-metadata/src/lib.rs +++ b/esp-metadata/src/lib.rs @@ -73,6 +73,7 @@ pub enum Cores { Eq, PartialOrd, Ord, + Hash, serde::Deserialize, serde::Serialize, strum::Display, diff --git a/xtask/src/lib.rs b/xtask/src/lib.rs index edc47577a28..9d468ae6b8c 100644 --- a/xtask/src/lib.rs +++ b/xtask/src/lib.rs @@ -1,5 +1,5 @@ use std::{ - collections::VecDeque, + collections::{HashMap, VecDeque}, fs::{self, File}, io::Write as _, path::{Path, PathBuf}, @@ -157,6 +157,7 @@ pub fn load_examples(path: &Path, action: CargoAction) -> Result> let mut chips = Chip::iter().collect::>(); 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("//%")) { @@ -164,23 +165,48 @@ pub fn load_examples(path: &Path, action: CargoAction) -> Result> bail!("Metadata line is missing ':': {}", line); }; - match key.trim() { - "CHIPS" => { - chips = value - .split_ascii_whitespace() - .map(|s| Chip::from_str(s, false).unwrap()) - .collect::>(); + let key = key.trim(); + + if key == "CHIPS" { + chips = value + .split_ascii_whitespace() + .map(|s| Chip::from_str(s, false).unwrap()) + .collect::>(); + } 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::>(); + + // Sort the features so they are in a deterministic order: + 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::>(); + + let values = value + .split_ascii_whitespace() + .map(ToString::to_string) + .collect::>(); + + for chip in chips { + chip_features.insert(chip, values.clone()); } - "FEATURES" => { - let mut values = value - .split_ascii_whitespace() - .map(ToString::to_string) - .collect::>(); - // Sort the features so they are in a deterministic order: - values.sort(); - feature_sets.push(values); - } - other => log::warn!("Unrecognized metadata key '{other}', ignoring"), + } else { + log::warn!("Unrecognized metadata key '{key}', ignoring"); } } @@ -195,6 +221,14 @@ pub fn load_examples(path: &Path, action: CargoAction) -> Result> } for feature_set in feature_sets { 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())); } }