diff --git a/crates/fbuild-build/src/esp32/orchestrator/build.rs b/crates/fbuild-build/src/esp32/orchestrator/build.rs index bbb1abfa..6af6780e 100644 --- a/crates/fbuild-build/src/esp32/orchestrator/build.rs +++ b/crates/fbuild-build/src/esp32/orchestrator/build.rs @@ -69,10 +69,19 @@ impl BuildOrchestrator for Esp32Orchestrator { mcu_config.architecture ); - // 4-6. Resolve platform, toolchain, and framework + // 4-6. Resolve platform, toolchain, and framework. + // Look up the env's `platform_packages` overrides so the platform + // (`platform-espressif32`) and framework (`framework-arduinoespressif32`) + // packages can honor consumer-pinned URLs (FastLED/fbuild#672). + let env_config = ctx.config.get_env_config(¶ms.env_name).ok(); let _resolve_phase = perf.phase("pioarduino-resolve"); - let (toolchain, framework) = - resolve_pioarduino_packages(¶ms.project_dir, &ctx.board.mcu, &mcu_config).await?; + let (toolchain, framework) = resolve_pioarduino_packages( + ¶ms.project_dir, + &ctx.board.mcu, + &mcu_config, + env_config, + ) + .await?; drop(_resolve_phase); let _toolchain_cache_dir = fbuild_packages::Package::get_info(&toolchain).install_path; let _framework_cache_dir = fbuild_packages::Package::get_info(&framework).install_path; diff --git a/crates/fbuild-build/src/esp32/orchestrator/packages.rs b/crates/fbuild-build/src/esp32/orchestrator/packages.rs index 74ac0ea3..f8faa15d 100644 --- a/crates/fbuild-build/src/esp32/orchestrator/packages.rs +++ b/crates/fbuild-build/src/esp32/orchestrator/packages.rs @@ -1,5 +1,6 @@ //! Package resolution for pioarduino (platform.json, framework, toolchain). +use std::collections::HashMap; use std::path::Path; use fbuild_core::Result; @@ -8,16 +9,32 @@ use fbuild_core::Result; /// /// Downloads pioarduino platform.json, resolves toolchain via metadata, /// and downloads the split framework + libs packages. +/// +/// `env_config` is the resolved `[env:]` section from `platformio.ini`, +/// used to honor `platform_packages` overrides for both +/// `platform-espressif32` and `framework-arduinoespressif32` +/// (FastLED/fbuild#672). Pass `None` if no env is in scope (cold-cache / +/// diagnostic paths) — both packages will fall back to their pinned defaults. pub(super) async fn resolve_pioarduino_packages( project_dir: &Path, mcu: &str, mcu_config: &super::super::mcu_config::Esp32McuConfig, + env_config: Option<&HashMap>, ) -> Result<( fbuild_packages::toolchain::Esp32Toolchain, fbuild_packages::library::Esp32Framework, )> { - // Ensure pioarduino platform (contains platform.json with metadata URLs) - let platform = fbuild_packages::library::Esp32Platform::new(project_dir); + // Ensure pioarduino platform (contains platform.json with metadata URLs). + // Honor `platform_packages = platform-espressif32@#` from the env + // section (FastLED/fbuild#672): if set, the override URL replaces the + // const-pinned default and gets its own cache subdir via + // `PackageBase::with_override`. + let platform_ovr = env_config + .and_then(|env| crate::package_override::resolve_override(env, "platform-espressif32")); + let platform = match platform_ovr { + Some(o) => fbuild_packages::library::Esp32Platform::with_override(project_dir, o), + None => fbuild_packages::library::Esp32Platform::new(project_dir), + }; fbuild_packages::Package::ensure_installed(&platform).await?; // Resolve toolchain via metadata @@ -32,16 +49,28 @@ pub(super) async fn resolve_pioarduino_packages( // See fbuild#401. provision_helper_toolchains(&platform, project_dir, mcu_config); - // Resolve framework - let framework = match platform.get_package_url("framework-arduinoespressif32") { - Ok(url) => { - tracing::info!("resolved framework URL from platform.json"); - fbuild_packages::library::Esp32Framework::from_url(project_dir, &url) - } - Err(e) => { - tracing::warn!("could not resolve framework URL, using legacy: {}", e); - fbuild_packages::library::Esp32Framework::new(project_dir, mcu) - } + // Resolve framework. Override precedence (FastLED/fbuild#672): + // 1. `platform_packages = framework-arduinoespressif32@#` wins + // outright — consumer-supplied URL replaces the platform.json-derived + // URL and gets its own cache subdir. + // 2. Otherwise, derive the URL from platform.json. + // 3. Otherwise (very old / missing platform.json), fall back to the + // legacy hardcoded URL via `Esp32Framework::new`. + let framework_ovr = env_config.and_then(|env| { + crate::package_override::resolve_override(env, "framework-arduinoespressif32") + }); + let framework = match framework_ovr { + Some(o) => fbuild_packages::library::Esp32Framework::with_override(project_dir, o), + None => match platform.get_package_url("framework-arduinoespressif32") { + Ok(url) => { + tracing::info!("resolved framework URL from platform.json"); + fbuild_packages::library::Esp32Framework::from_url(project_dir, &url) + } + Err(e) => { + tracing::warn!("could not resolve framework URL, using legacy: {}", e); + fbuild_packages::library::Esp32Framework::new(project_dir, mcu) + } + }, }; // Ensure framework is installed before trying to install libs diff --git a/crates/fbuild-packages/src/library/esp32_framework/mod.rs b/crates/fbuild-packages/src/library/esp32_framework/mod.rs index 871feed3..b62b3884 100644 --- a/crates/fbuild-packages/src/library/esp32_framework/mod.rs +++ b/crates/fbuild-packages/src/library/esp32_framework/mod.rs @@ -95,6 +95,30 @@ impl Esp32Framework { } } + /// Construct with a consumer-supplied override (parsed from the env's + /// `platform_packages` line in `platformio.ini`). The default + /// `platform.json`-resolved URL / version / checksum are replaced; + /// `cache_subdir` and `name` are preserved. See `PackageBase::with_override` + /// and FastLED/fbuild#672. + /// + /// The override completely supersedes the platform.json-derived URL — + /// there is no merge; the consumer's URL wins outright. + pub fn with_override(project_dir: &Path, ovr: fbuild_config::PackageOverride) -> Self { + Self { + base: PackageBase::new( + "esp32-arduino", + ESP32_FRAMEWORK_VERSION, + ESP32_FRAMEWORK_URL, + "framework-arduinoespressif32", + None, + CacheSubdir::Platforms, + project_dir, + ) + .with_override(ovr), + install_dir: None, + } + } + /// Get the resolved root directory of the framework. pub(crate) fn resolved_dir(&self) -> PathBuf { self.install_dir diff --git a/crates/fbuild-packages/src/library/esp32_platform.rs b/crates/fbuild-packages/src/library/esp32_platform.rs index 5eab3113..7689bb98 100644 --- a/crates/fbuild-packages/src/library/esp32_platform.rs +++ b/crates/fbuild-packages/src/library/esp32_platform.rs @@ -39,6 +39,26 @@ impl Esp32Platform { } } + /// Construct with a consumer-supplied override (parsed from the env's + /// `platform_packages` line in `platformio.ini`). The default const-pinned + /// URL / version / checksum are replaced; `cache_subdir` and `name` are + /// preserved. See `PackageBase::with_override` and FastLED/fbuild#672. + pub fn with_override(project_dir: &Path, ovr: fbuild_config::PackageOverride) -> Self { + Self { + base: PackageBase::new( + "platform-espressif32", + PLATFORM_VERSION, + PLATFORM_URL, + PLATFORM_URL, + None, // No checksum for stable release (content changes) + CacheSubdir::Platforms, + project_dir, + ) + .with_override(ovr), + install_dir: None, + } + } + #[cfg(test)] fn with_cache_root(project_dir: &Path, cache_root: &Path) -> Self { Self {