diff --git a/crates/rugpi-bakery/src/bake/mod.rs b/crates/rugpi-bakery/src/bake/mod.rs index f13fd47..b9c7278 100644 --- a/crates/rugpi-bakery/src/bake/mod.rs +++ b/crates/rugpi-bakery/src/bake/mod.rs @@ -32,7 +32,9 @@ pub fn bake_layer(project: &Project, arch: Architecture, layer: &str) -> Anyhow< let library = project.load_library()?; let layer_config = &library.layers[library .lookup_layer(library.repositories.root_repository, layer) - .unwrap()]; + .unwrap()] + .config(arch) + .unwrap(); if let Some(url) = &layer_config.url { let layer_id = sha1(url); let system_tar = project diff --git a/crates/rugpi-bakery/src/project/config.rs b/crates/rugpi-bakery/src/project/config.rs index 9628e0e..b3c29f4 100644 --- a/crates/rugpi-bakery/src/project/config.rs +++ b/crates/rugpi-bakery/src/project/config.rs @@ -1,11 +1,12 @@ //! Project configuration. -use std::{collections::HashMap, fs, path::Path}; +use std::{collections::HashMap, fs, path::Path, str::FromStr}; use anyhow::Context; use clap::ValueEnum; use rugpi_common::Anyhow; use serde::{Deserialize, Serialize}; +use thiserror::Error; use super::{images::ImageConfig, repositories::Source}; @@ -40,7 +41,7 @@ pub enum IncludeFirmware { Pi5, } -#[derive(Debug, Clone, Copy, Serialize, Deserialize, Default, ValueEnum)] +#[derive(Debug, Clone, Copy, Serialize, Deserialize, Default, PartialEq, Eq, Hash, ValueEnum)] #[clap(rename_all = "lowercase")] #[serde(rename_all = "lowercase")] pub enum Architecture { @@ -49,6 +50,22 @@ pub enum Architecture { Armhf, } +#[derive(Debug, Error)] +#[error("invalid architecture")] +pub struct InvalidArchitectureError; + +impl FromStr for Architecture { + type Err = InvalidArchitectureError; + + fn from_str(s: &str) -> Result { + match s { + "arm64" => Ok(Self::Arm64), + "armhf" => Ok(Self::Armhf), + _ => Err(InvalidArchitectureError), + } + } +} + impl Architecture { pub fn as_str(self) -> &'static str { match self { diff --git a/crates/rugpi-bakery/src/project/layers.rs b/crates/rugpi-bakery/src/project/layers.rs index 48b45da..61862a4 100644 --- a/crates/rugpi-bakery/src/project/layers.rs +++ b/crates/rugpi-bakery/src/project/layers.rs @@ -8,11 +8,16 @@ use anyhow::Context; use rugpi_common::Anyhow; use serde::{Deserialize, Serialize}; -use super::recipes::{ParameterValue, RecipeName}; +use super::{ + config::Architecture, + recipes::{ParameterValue, RecipeName}, +}; #[derive(Debug, Clone, Serialize, Deserialize)] #[serde(deny_unknown_fields)] pub struct LayerConfig { + /// Optional human-readable name of the layer. + pub name: Option, /// An URL to fetch the layer from. pub url: Option, pub parent: Option, @@ -36,3 +41,18 @@ impl LayerConfig { .with_context(|| format!("error parsing layer config from path `{path:?}`")) } } + +#[derive(Debug, Default)] +pub struct Layer { + pub default_config: Option, + pub arch_configs: HashMap, +} + +impl Layer { + /// The layer configuration for the given architecture. + pub fn config(&self, arch: Architecture) -> Option<&LayerConfig> { + self.arch_configs + .get(&arch) + .or(self.default_config.as_ref()) + } +} diff --git a/crates/rugpi-bakery/src/project/library.rs b/crates/rugpi-bakery/src/project/library.rs index b298e28..23adb0a 100644 --- a/crates/rugpi-bakery/src/project/library.rs +++ b/crates/rugpi-bakery/src/project/library.rs @@ -1,9 +1,10 @@ -use std::{collections::HashMap, fs, ops::Deref, sync::Arc}; +use std::{collections::HashMap, fs, ops::Deref, str::FromStr, sync::Arc}; use rugpi_common::Anyhow; use super::{ - layers::LayerConfig, + config::Architecture, + layers::{Layer, LayerConfig}, recipes::{Recipe, RecipeLoader}, repositories::{ProjectRepositories, RepositoryIdx}, }; @@ -12,7 +13,7 @@ use crate::idx_vec::{new_idx_type, IdxVec}; pub struct Library { pub repositories: ProjectRepositories, pub recipes: IdxVec>, - pub layers: IdxVec, + pub layers: IdxVec, pub recipe_tables: IdxVec>, pub layer_tables: IdxVec>, } @@ -52,10 +53,24 @@ impl Library { for entry in fs::read_dir(layers_dir)? { let entry = entry?; let path = entry.path(); - let layer_name = path.file_stem().unwrap(); + let mut name = path.file_stem().unwrap().to_string_lossy().into_owned(); + let mut arch = None; + if let Some((layer_name, arch_str)) = name.split_once('.') { + arch = Some(Architecture::from_str(arch_str)?); + name = layer_name.to_owned(); + } let layer_config = LayerConfig::load(&path)?; - let layer_idx = layers.push(layer_config); - table.insert(layer_name.to_string_lossy().into_owned(), layer_idx); + let layer_idx = *table + .entry(name) + .or_insert_with(|| layers.push(Layer::default())); + match arch { + Some(arch) => { + layers[layer_idx].arch_configs.insert(arch, layer_config); + } + None => { + layers[layer_idx].default_config = Some(layer_config); + } + } } Ok(table) }) diff --git a/repositories/core/layers/raspios-bookworm.arm64.toml b/repositories/core/layers/raspios-bookworm.arm64.toml new file mode 100644 index 0000000..1d28e00 --- /dev/null +++ b/repositories/core/layers/raspios-bookworm.arm64.toml @@ -0,0 +1,2 @@ +name = "Raspberry Pi OS (Bookworm)" +url = "https://downloads.raspberrypi.com/raspios_lite_arm64/images/raspios_lite_arm64-2023-12-11/2023-12-11-raspios-bookworm-arm64-lite.img.xz" \ No newline at end of file diff --git a/repositories/core/layers/raspios-bookworm.armhf.toml b/repositories/core/layers/raspios-bookworm.armhf.toml new file mode 100644 index 0000000..e3cbf0b --- /dev/null +++ b/repositories/core/layers/raspios-bookworm.armhf.toml @@ -0,0 +1,2 @@ +name = "Raspberry Pi OS (Bookworm)" +url = "https://downloads.raspberrypi.com/raspios_lite_armhf/images/raspios_lite_armhf-2023-12-11/2023-12-11-raspios-bookworm-armhf-lite.img.xz" \ No newline at end of file diff --git a/repositories/core/layers/raspios-bullseye.arm64.toml b/repositories/core/layers/raspios-bullseye.arm64.toml new file mode 100644 index 0000000..166ff12 --- /dev/null +++ b/repositories/core/layers/raspios-bullseye.arm64.toml @@ -0,0 +1,2 @@ +name = "Raspberry Pi OS (Bullseye)" +url = "https://downloads.raspberrypi.com/raspios_oldstable_lite_arm64/images/raspios_oldstable_lite_arm64-2023-12-06/2023-12-05-raspios-bullseye-arm64-lite.img.xz" \ No newline at end of file diff --git a/repositories/core/layers/raspios-bullseye.armhf.toml b/repositories/core/layers/raspios-bullseye.armhf.toml new file mode 100644 index 0000000..5ad6d8a --- /dev/null +++ b/repositories/core/layers/raspios-bullseye.armhf.toml @@ -0,0 +1,2 @@ +name = "Raspberry Pi OS (Bullseye)" +url = "https://downloads.raspberrypi.com/raspios_oldstable_lite_armhf/images/raspios_oldstable_lite_armhf-2023-12-06/2023-12-05-raspios-bullseye-armhf-lite.img.xz" \ No newline at end of file diff --git a/template b/template index 929a30d..a63c081 160000 --- a/template +++ b/template @@ -1 +1 @@ -Subproject commit 929a30d7c28c6e9878790c9de7c2280acde14a30 +Subproject commit a63c081d0f5ed6b54e2213b51dbab7be90135336