diff --git a/crates/fbuild-build-engine/src/package_override.rs b/crates/fbuild-build-engine/src/package_override.rs index c3f98d225..d1cddb973 100644 --- a/crates/fbuild-build-engine/src/package_override.rs +++ b/crates/fbuild-build-engine/src/package_override.rs @@ -578,6 +578,45 @@ mod tests { } } + #[test] + fn pinned_megaavr_tiny_core_selects_newer_avr_toolchain() { + let manifest = r#"{"packages":{"framework-arduino-megaavr-megatinycore":{"type":"framework","owner":"platformio","version":"~2.6.11","optional":true},"toolchain-atmelavr":{"type":"toolchain","owner":"platformio","version":"~1.70300.0","optionalVersions":["~3.70300.0"]}}}"#; + let builder = " if build_core in (\"megatinycore\", \"dxcore\"):\n self.packages[\"toolchain-atmelavr\"][\"version\"] = \"~3.70300.0\"\n"; + let defaults = [( + "toolchain-atmelavr", + PlatformDefaultVersion::BuilderBranch { + marker: "if build_core in (\"megatinycore\", \"dxcore\"):", + after: None, + }, + )]; + let requirements = + requirements_with_platform_defaults(manifest, Some(builder), &[], &defaults).unwrap(); + assert_eq!( + require_platform_package(&requirements, "toolchain-atmelavr") + .unwrap() + .spec + .registry() + .unwrap() + .requirement + .as_deref(), + Some("~3.70300.0") + ); + let explicit = parse_package_spec("toolchain-atmelavr@1.70300.191015").unwrap(); + let requirements = + requirements_with_platform_defaults(manifest, Some(builder), &[explicit], &defaults) + .unwrap(); + assert_eq!( + require_platform_package(&requirements, "toolchain-atmelavr") + .unwrap() + .spec + .registry() + .unwrap() + .requirement + .as_deref(), + Some("1.70300.191015") + ); + } + #[test] fn pinned_sam_builder_selects_adafruit_gcc_and_rejects_changed_rule() { let builder = " if build_core == \"adafruit\":\n self.packages[\"toolchain-gccarmnoneeabi\"][\"version\"] = \"~1.90301.0\"\n"; diff --git a/crates/fbuild-build-engine/src/pipeline/context.rs b/crates/fbuild-build-engine/src/pipeline/context.rs index eeb3a7f29..610707f72 100644 --- a/crates/fbuild-build-engine/src/pipeline/context.rs +++ b/crates/fbuild-build-engine/src/pipeline/context.rs @@ -186,6 +186,10 @@ impl BuildContext { Some(fbuild_core::Platform::RaspberryPi) => { Some(fbuild_core::Platform::RaspberryPi) } + Some(fbuild_core::Platform::AtmelAvr) => Some(fbuild_core::Platform::AtmelAvr), + Some(fbuild_core::Platform::AtmelMegaAvr) => { + Some(fbuild_core::Platform::AtmelMegaAvr) + } _ => None, }; let resolved_packages: &[&str] = match resolved_platform { @@ -231,6 +235,29 @@ impl BuildContext { "toolchain-rp2040-earlephilhower", "tool-picotool-rp2040-earlephilhower", ], + Some(fbuild_core::Platform::AtmelAvr) => &[ + "framework-arduino-avr", + "framework-arduino-avr-attiny", + "framework-arduino-avr-digistump", + "framework-arduino-avr-minicore", + "framework-arduino-avr-majorcore", + "framework-arduino-avr-megacore", + "framework-arduino-avr-microcore", + "framework-arduino-avr-mightycore", + "framework-arduino-avr-bean", + "framework-arduino-avr-dwenguino", + "framework-arduino-avr-nicai", + "framework-arduino-avr-panstamp", + "framework-arduino-avr-prusa_rambo", + "toolchain-atmelavr", + ], + Some(fbuild_core::Platform::AtmelMegaAvr) => &[ + "framework-arduino-megaavr", + "framework-arduino-megaavr-megacorex", + "framework-arduino-megaavr-megatinycore", + "framework-arduino-megaavr-dxcore", + "toolchain-atmelavr", + ], _ => &[], }; for warning in fbuild_config::ignored_version_pins_with_resolved_packages( diff --git a/crates/fbuild-build-mcu/src/avr/mod.rs b/crates/fbuild-build-mcu/src/avr/mod.rs index 07bca26c0..76e00e99c 100644 --- a/crates/fbuild-build-mcu/src/avr/mod.rs +++ b/crates/fbuild-build-mcu/src/avr/mod.rs @@ -25,7 +25,8 @@ impl crate::PlatformSupport for AvrPlatformSupport { ) -> fbuild_core::Result> { use crate::provision::{PackageKind, provision_package}; let (toolchain, framework) = - orchestrator::avr_packages(inputs.project_dir, Some(inputs.env_config), inputs.board)?; + orchestrator::avr_packages(inputs.project_dir, Some(inputs.env_config), inputs.board) + .await?; Ok(vec![ provision_package(PackageKind::Toolchain, &toolchain, mode).await, provision_package(PackageKind::Framework, &framework, mode).await, diff --git a/crates/fbuild-build-mcu/src/avr/orchestrator.rs b/crates/fbuild-build-mcu/src/avr/orchestrator.rs index aabc41e2e..5666218f3 100644 --- a/crates/fbuild-build-mcu/src/avr/orchestrator.rs +++ b/crates/fbuild-build-mcu/src/avr/orchestrator.rs @@ -98,23 +98,37 @@ impl BuildOrchestrator for AvrOrchestrator { // 3-4. Resolve the avr-gcc toolchain and Arduino core packages. // - // Honor `platform_packages = framework-arduino-avr@` (FastLED/fbuild#667) - // and `platform_packages = framework-arduino-avr-attiny@` - // (FastLED/fbuild#669) from the env section. The PIO atmelavr platform - // exposes the standard Arduino core as `framework-arduino-avr` and the - // ATTinyCore-based ATtiny core as `framework-arduino-avr-attiny` - // (see https://github.com/platformio/platform-atmelavr/blob/develop/platform.json); - // those names are the canonical override keys consumers will set in - // their `platformio.ini`. The non-ATtiny "tinyX/MiniCore/etc." JSON - // entries currently share the `framework-arduino-avr` override key — - // they all fall under the atmelavr platform — but only the two PIO - // canonical names are resolved here. If those alt-core PIO package - // names land in the registry later, add additional resolution branches. - let (toolchain, framework) = avr_packages( - ¶ms.project_dir, - ctx.config.get_env_config(¶ms.env_name).ok(), - &ctx.board, - )?; + // The board core selects the PlatformIO framework package name. + // Registry pins resolve exact payloads; URL overrides keep their + // existing precedence and cache identity. + let env_config = ctx.config.get_env_config(¶ms.env_name).ok(); + let (toolchain, framework) = + avr_packages(¶ms.project_dir, env_config, &ctx.board).await?; + use fbuild_packages::Package as _; + let toolchain_info = toolchain.get_info(); + let framework_info = framework.get_info(); + if let Some(env) = env_config { + let platform_request = env + .get("platform") + .map(String::as_str) + .unwrap_or("atmelavr"); + let package_request = env + .get("platform_packages") + .map(|value| value.split_whitespace().collect::>().join(", ")) + .unwrap_or_else(|| "(default)".to_string()); + ctx.build_log.push(format!( + "AVR requested: platform={platform_request}; platform_packages={package_request}" + )); + } + ctx.build_log.push(format!( + "AVR resolved: {}@{} ({}); {}@{} ({})", + toolchain_info.name, + toolchain_info.version, + toolchain_info.url, + framework_info.name, + framework_info.version, + framework_info.url, + )); // 3. Ensure toolchain let toolchain_dir = { @@ -381,30 +395,99 @@ pub fn create() -> Box { } /// The avr-gcc toolchain and the Arduino framework package for an env's board, -/// honoring the `framework-arduino-avr` / `framework-arduino-avr-attiny` -/// `platform_packages` overrides. Shared by the build and `fbuild install`, so -/// both provision the same packages (FastLED/fbuild#1433). -pub(crate) fn avr_packages( +/// honoring board-specific `platform_packages` and versioned `platform` +/// aliases. Shared by the build and `fbuild install`, so both provision the +/// same packages (FastLED/fbuild#1433, #1494). +pub(crate) async fn avr_packages( + project_dir: &Path, + env_config: Option<&std::collections::HashMap>, + board: &fbuild_config::BoardConfig, +) -> Result<( + fbuild_packages::toolchain::AvrToolchain, + fbuild_packages::library::AvrFramework, +)> { + let platform = board.platform(); + let (_, framework_name) = avr_core_package(&board.core, platform)?; + let platform_name = if platform == Some(Platform::AtmelMegaAvr) { + "atmelmegaavr" + } else { + "atmelavr" + }; + let registry_overrides = if let Some(env) = env_config { + let mega_toolchain_defaults = [( + "toolchain-atmelavr", + crate::package_override::PlatformDefaultVersion::BuilderBranch { + marker: "if build_core in (\"megatinycore\", \"dxcore\"):", + after: None, + }, + )]; + let defaults = if platform == Some(Platform::AtmelMegaAvr) + && matches!(board.core.as_str(), "megatinycore" | "dxcore") + { + &mega_toolchain_defaults[..] + } else { + &[][..] + }; + crate::package_override::resolve_registry_overrides( + project_dir, + env, + platform_name, + &[framework_name, "toolchain-atmelavr"], + defaults, + ) + .await? + } else { + std::collections::HashMap::new() + }; + avr_packages_from_resolved(project_dir, env_config, board, ®istry_overrides) +} + +fn avr_packages_from_resolved( project_dir: &Path, env_config: Option<&std::collections::HashMap>, board: &fbuild_config::BoardConfig, + registry_overrides: &std::collections::HashMap, ) -> Result<( fbuild_packages::toolchain::AvrToolchain, fbuild_packages::library::AvrFramework, )> { - let toolchain = fbuild_packages::toolchain::AvrToolchain::new(project_dir); - let avr_override = env_config - .and_then(|env| crate::package_override::resolve_override(env, "framework-arduino-avr")); - let attiny_override = env_config.and_then(|env| { - crate::package_override::resolve_override(env, "framework-arduino-avr-attiny") + let (core_key, framework_name) = avr_core_package(&board.core, board.platform())?; + let toolchain_override = registry_overrides + .get("toolchain-atmelavr") + .cloned() + .or_else(|| { + env_config.and_then(|env| { + crate::package_override::resolve_override(env, "toolchain-atmelavr") + }) + }); + let toolchain = match toolchain_override { + Some(ovr) => fbuild_packages::toolchain::AvrToolchain::with_override(project_dir, ovr), + None => fbuild_packages::toolchain::AvrToolchain::new(project_dir), + }; + let framework_override = registry_overrides.get(framework_name).cloned().or_else(|| { + env_config.and_then(|env| crate::package_override::resolve_override(env, framework_name)) }); - let framework = avr_framework_package( - project_dir, - &board.core, - board.platform(), - avr_override, - attiny_override, - )?; + let framework = match framework_override { + Some(ovr) => fbuild_packages::library::AvrFramework::for_core_with_override( + core_key, + project_dir, + ovr, + )?, + None => fbuild_packages::library::AvrFramework::for_core(core_key, project_dir)?, + }; + use fbuild_packages::Package as _; + let toolchain_info = toolchain.get_info(); + let framework_info = framework.get_info(); + tracing::info!( + "AVR packages for core `{}`: toolchain {}@{} ({}), framework {}@{} ({})", + board.core, + toolchain_info.name, + toolchain_info.version, + toolchain_info.url, + framework_info.name, + framework_info.version, + framework_info.url, + ); Ok((toolchain, framework)) } @@ -430,27 +513,12 @@ async fn ensure_avr_framework( Ok((framework_dir, core_dir, variant_dir)) } -/// Select the correct AVR Arduino framework package based on the board's core name. -/// -/// Uses the data-driven `avr_frameworks.json` registry to resolve the correct -/// framework package (GitHub URL, version) for any board core. -/// For `AtmelMegaAvr` boards whose core is `"arduino"`, the lookup key is remapped -/// to `"arduino_megaavr"` so they get `ArduinoCore-megaavr` (which contains the -/// megaAVR variants like `nona4809`) instead of `ArduinoCore-avr`. -/// -/// `avr_override` / `attiny_override` are pre-resolved `platform_packages` -/// overrides for `framework-arduino-avr` and `framework-arduino-avr-attiny` -/// respectively (FastLED/fbuild#667, #669). When set, the resolved URL -/// supersedes the registry-pinned default; the cache subdir is derived from -/// the override URL via `PackageBase::with_override` so an override doesn't -/// collide with the default cache entry. -fn avr_framework_package( - project_dir: &Path, +/// Map a board core to its local framework key and PlatformIO package alias. +/// megaAVR `arduino` uses a distinct package from standard AVR `arduino`. +fn avr_core_package( core_name: &str, platform: Option, - avr_override: Option, - attiny_override: Option, -) -> fbuild_core::Result { +) -> fbuild_core::Result<(&str, &'static str)> { // megaAVR boards (e.g. nano_every) share core name "arduino" with standard AVR // but need ArduinoCore-megaavr instead of ArduinoCore-avr. let lookup_key = @@ -460,27 +528,31 @@ fn avr_framework_package( core_name }; - // Route the appropriate `platform_packages` override to the matching PIO - // package. `framework-arduino-avr` covers the standard ArduinoCore-avr - // (board core "arduino" on the atmelavr platform); - // `framework-arduino-avr-attiny` covers SpenceKonde/ATTinyCore (board cores - // "tiny" and "tinymodern"). Other JSON entries (MiniCore, MegaCoreX, - // digistump, megatinycore, megaavr) ignore both overrides — their PIO - // package names are distinct and aren't wired in this PR. - let routed_override = match lookup_key { - "arduino" => avr_override, - "tiny" | "tinymodern" => attiny_override, - _ => None, + let package = match (platform, lookup_key) { + (Some(Platform::AtmelMegaAvr), "arduino_megaavr") => "framework-arduino-megaavr", + (Some(Platform::AtmelMegaAvr), "MegaCoreX") => "framework-arduino-megaavr-megacorex", + (Some(Platform::AtmelMegaAvr), "megatinycore") => "framework-arduino-megaavr-megatinycore", + (Some(Platform::AtmelMegaAvr), "dxcore") => "framework-arduino-megaavr-dxcore", + (_, "arduino") => "framework-arduino-avr", + (_, "tiny" | "tinymodern") => "framework-arduino-avr-attiny", + (_, "dtiny" | "pro") => "framework-arduino-avr-digistump", + (_, "MiniCore") => "framework-arduino-avr-minicore", + (_, "MajorCore") => "framework-arduino-avr-majorcore", + (_, "MegaCore") => "framework-arduino-avr-megacore", + (_, "MicroCore") => "framework-arduino-avr-microcore", + (_, "MightyCore") => "framework-arduino-avr-mightycore", + (_, "bean") => "framework-arduino-avr-bean", + (_, "dwenguino") => "framework-arduino-avr-dwenguino", + (_, "nicai") => "framework-arduino-avr-nicai", + (_, "panstamp") => "framework-arduino-avr-panstamp", + (_, "prusa_rambo") => "framework-arduino-avr-prusa_rambo", + _ => { + return Err(fbuild_core::FbuildError::ConfigError(format!( + "unsupported AVR framework core `{core_name}`" + ))); + } }; - - match routed_override { - Some(ovr) => fbuild_packages::library::AvrFramework::for_core_with_override( - lookup_key, - project_dir, - ovr, - ), - None => fbuild_packages::library::AvrFramework::for_core(lookup_key, project_dir), - } + Ok((lookup_key, package)) } /// Check if a project is configured for AVR by reading its platformio.ini. @@ -521,6 +593,132 @@ mod tests { assert!(!is_avr_project(tmp.path(), "esp32")); } + #[test] + fn minicore_registry_pin_must_not_fall_back_to_embedded_default() { + use fbuild_packages::Package as _; + + let project = tempfile::TempDir::new().unwrap(); + let board = + fbuild_config::BoardConfig::from_board_id("ATmega8", &std::collections::HashMap::new()) + .unwrap(); + assert_eq!(board.core, "MiniCore"); + let env = std::collections::HashMap::from([ + ("platform".to_string(), "atmelavr".to_string()), + ( + "platform_packages".to_string(), + "framework-arduino-avr-minicore@3.1.2".to_string(), + ), + ]); + let registry_overrides = std::collections::HashMap::from([( + "framework-arduino-avr-minicore".to_string(), + fbuild_config::PackageOverride { + url: "https://dl.registry.platformio.org/download/platformio/tool/framework-arduino-avr-minicore/3.1.2/framework-arduino-avr-minicore-3.1.2.tar.gz".to_string(), + version: "3.1.2".to_string(), + checksum: Some("3cc43553f35d2d00a277d488eefba628816104ae61a9ca9cecd60470f555c9f6".to_string()), + }, + )]); + let (_, framework) = + avr_packages_from_resolved(project.path(), Some(&env), &board, ®istry_overrides) + .unwrap(); + assert_eq!(framework.get_info().version, "3.1.2"); + assert_eq!( + framework.get_info().checksum.as_deref(), + Some("3cc43553f35d2d00a277d488eefba628816104ae61a9ca9cecd60470f555c9f6") + ); + } + + #[test] + fn avr_board_cores_select_their_platformio_package_names() { + for (board_id, expected_name) in [ + ("uno", "framework-arduino-avr"), + ("attiny44", "framework-arduino-avr-attiny"), + ("ATmega8", "framework-arduino-avr-minicore"), + ("nano_every", "framework-arduino-megaavr"), + ("curiosity_nano_4809", "framework-arduino-megaavr-megacorex"), + ("ATtiny1616", "framework-arduino-megaavr-megatinycore"), + ] { + let board = fbuild_config::BoardConfig::from_board_id( + board_id, + &std::collections::HashMap::new(), + ) + .unwrap(); + assert_eq!( + avr_core_package(&board.core, board.platform()).unwrap().1, + expected_name, + "{board_id}" + ); + } + } + + #[test] + fn avr_adapter_uses_resolved_framework_and_toolchain_payloads() { + use fbuild_packages::Package as _; + + let project = tempfile::TempDir::new().unwrap(); + let board = fbuild_config::BoardConfig::from_board_id( + "nano_every", + &std::collections::HashMap::new(), + ) + .unwrap(); + let overrides = std::collections::HashMap::from([ + ( + "framework-arduino-megaavr".to_string(), + fbuild_config::PackageOverride { + url: "https://example.test/megaavr-1.8.8.tar.gz".to_string(), + version: "1.8.8".to_string(), + checksum: Some( + "7f13029f3a4621c89c4676bd6192f39ef5de3b9dd77316e9931d9b07e56411d7" + .to_string(), + ), + }, + ), + ( + "toolchain-atmelavr".to_string(), + fbuild_config::PackageOverride { + url: "https://example.test/avr-gcc-1.70300.191015.tar.gz".to_string(), + version: "1.70300.191015".to_string(), + checksum: Some( + "664f0b7b08a15e8d6362b87e2fdb5a4dcfd5959ebc5b19d938e7dff6f12f0524" + .to_string(), + ), + }, + ), + ]); + let (toolchain, framework) = + avr_packages_from_resolved(project.path(), None, &board, &overrides).unwrap(); + assert_eq!(toolchain.get_info().version, "1.70300.191015"); + assert_eq!(framework.get_info().version, "1.8.8"); + assert_ne!( + toolchain.get_info().install_path, + framework.get_info().install_path + ); + } + + #[test] + fn avr_archive_url_override_keeps_precedence_without_registry_lookup() { + use fbuild_packages::Package as _; + + let project = tempfile::TempDir::new().unwrap(); + let board = + fbuild_config::BoardConfig::from_board_id("ATmega8", &std::collections::HashMap::new()) + .unwrap(); + let env = std::collections::HashMap::from([( + "platform_packages".to_string(), + "framework-arduino-avr-minicore@https://example.test/minicore-custom.tar.gz" + .to_string(), + )]); + let (_, framework) = avr_packages_from_resolved( + project.path(), + Some(&env), + &board, + &std::collections::HashMap::new(), + ) + .unwrap(); + let info = framework.get_info(); + assert_eq!(info.url, "https://example.test/minicore-custom.tar.gz"); + assert_ne!(info.version, "2.2.2"); + } + /// Verify that megaAVR boards remap "arduino" core to "arduino_megaavr" framework. #[test] fn test_megaavr_core_remaps_to_megaavr_framework() { diff --git a/crates/fbuild-core/tests/platformio_avr_resolution.rs b/crates/fbuild-core/tests/platformio_avr_resolution.rs new file mode 100644 index 000000000..974dd11ec --- /dev/null +++ b/crates/fbuild-core/tests/platformio_avr_resolution.rs @@ -0,0 +1,158 @@ +//! Offline AVR and megaAVR PlatformIO registry payload fixtures. + +use fbuild_core::platformio_package::{ + PackageKind, parse_package_spec, require_platform_package, resolve_platform_requirements, + resolve_registry_json, +}; + +#[test] +fn avr_and_megaavr_board_packages_resolve_exact_payloads_offline() { + // Published registry metadata and platform manifests, captured 2026-09-27. + // These generic-path tests deliberately do not dispatch on Platform. + let cases = [ + ( + "atmelavr", + "5.3.0", + "370a482b8cd980b8954c03cec3e856f50758cac695491e6b6c8327f5e60079ac", + "framework-arduino-avr-minicore", + "3.1.2", + "3cc43553f35d2d00a277d488eefba628816104ae61a9ca9cecd60470f555c9f6", + "~3.1.0", + "~1.70300.0", + ), + ( + "atmelavr", + "5.3.0", + "370a482b8cd980b8954c03cec3e856f50758cac695491e6b6c8327f5e60079ac", + "framework-arduino-avr", + "5.4.0", + "bf85bcca114bad389fec51fecbf9b66821a233b366bd3f85cdb1cdcba6a28659", + "~5.4.0", + "~1.70300.0", + ), + ( + "atmelavr", + "5.3.0", + "370a482b8cd980b8954c03cec3e856f50758cac695491e6b6c8327f5e60079ac", + "framework-arduino-avr-attiny", + "1.5.2", + "06665ec79058cd180b82d76a2bc6bd30fc5311d9eebaed56dc57389f325822ee", + "~1.5.2", + "~1.70300.0", + ), + ( + "atmelmegaavr", + "1.10.0", + "36f2d93a3865dcc543668f260479973ec70a15f120ba97bb130bc320ab8b4f08", + "framework-arduino-megaavr", + "1.8.8", + "7f13029f3a4621c89c4676bd6192f39ef5de3b9dd77316e9931d9b07e56411d7", + "~1.8.8", + "~1.70300.0", + ), + ]; + for ( + platform_name, + platform_version, + platform_sha, + framework_name, + framework_version, + framework_sha, + framework_range, + toolchain_range, + ) in cases + { + let platform = parse_package_spec(&format!( + "platformio/platform/{platform_name}@{platform_version}" + )) + .unwrap(); + let platform_url = format!( + "https://dl.registry.platformio.org/download/platformio/platform/{platform_name}/{platform_version}/{platform_name}-{platform_version}.tar.gz" + ); + let platform_metadata = format!( + r#"{{"name":"{platform_name}","owner":{{"username":"platformio"}},"versions":[{{"name":"{platform_version}","files":[{{"system":"*","download_url":"{platform_url}","checksum":{{"sha256":"{platform_sha}"}}}}]}}]}}"# + ); + let platform_payload = resolve_registry_json( + platform.registry().unwrap(), + PackageKind::Platform, + "linux_x86_64", + &platform_metadata, + ) + .unwrap(); + assert_eq!(platform_payload.url, platform_url); + assert_eq!(platform_payload.sha256, platform_sha); + + let manifest = format!( + r#"{{"packages":{{"{framework_name}":{{"type":"framework","owner":"platformio","version":"{framework_range}","optional":true}},"toolchain-atmelavr":{{"type":"toolchain","owner":"platformio","version":"{toolchain_range}"}}}}}}"# + ); + let override_spec = parse_package_spec(&format!( + "tool/platformio/{framework_name}@{framework_version}" + )) + .unwrap(); + let requirements = resolve_platform_requirements(&manifest, &[override_spec]).unwrap(); + let framework = require_platform_package(&requirements, framework_name).unwrap(); + assert_eq!( + framework.spec.registry().unwrap().requirement.as_deref(), + Some(framework_version) + ); + assert_eq!(framework.kind, PackageKind::Framework); + let framework_url = format!( + "https://dl.registry.platformio.org/download/platformio/tool/{framework_name}/{framework_version}/{framework_name}-{framework_version}.tar.gz" + ); + let framework_metadata = format!( + r#"{{"name":"{framework_name}","owner":{{"username":"platformio"}},"versions":[{{"name":"{framework_version}","files":[{{"system":"*","download_url":"{framework_url}","checksum":{{"sha256":"{framework_sha}"}}}}]}}]}}"# + ); + let framework_payload = resolve_registry_json( + framework.spec.registry().unwrap(), + framework.kind, + "linux_x86_64", + &framework_metadata, + ) + .unwrap(); + assert_eq!(framework_payload.url, framework_url); + assert_eq!(framework_payload.sha256, framework_sha); + assert_ne!( + framework_payload.cache_identity(), + platform_payload.cache_identity() + ); + let toolchain = require_platform_package(&requirements, "toolchain-atmelavr").unwrap(); + assert_eq!( + toolchain.spec.registry().unwrap().requirement.as_deref(), + Some(toolchain_range) + ); + let toolchain_url = "https://dl.registry.platformio.org/download/platformio/tool/toolchain-atmelavr/1.70300.191015/toolchain-atmelavr-linux_x86_64-1.70300.191015.tar.gz"; + let toolchain_sha = "664f0b7b08a15e8d6362b87e2fdb5a4dcfd5959ebc5b19d938e7dff6f12f0524"; + let toolchain_metadata = format!( + r#"{{"name":"toolchain-atmelavr","owner":{{"username":"platformio"}},"versions":[{{"name":"1.70300.191015","files":[{{"system":"linux_x86_64","download_url":"{toolchain_url}","checksum":{{"sha256":"{toolchain_sha}"}}}}]}}]}}"# + ); + let toolchain_payload = resolve_registry_json( + toolchain.spec.registry().unwrap(), + toolchain.kind, + "linux_x86_64", + &toolchain_metadata, + ) + .unwrap(); + assert_eq!(toolchain_payload.version, "1.70300.191015"); + assert_eq!(toolchain_payload.url, toolchain_url); + assert_eq!(toolchain_payload.sha256, toolchain_sha); + assert_ne!( + toolchain_payload.cache_identity(), + framework_payload.cache_identity() + ); + } +} + +#[test] +fn unavailable_exact_minicore_pin_does_not_fall_back_to_older_core() { + let metadata = r#"{"name":"framework-arduino-avr-minicore","owner":{"username":"platformio"},"versions":[{"name":"3.1.2","files":[{"system":"*","download_url":"https://dl.registry.platformio.org/download/platformio/tool/framework-arduino-avr-minicore/3.1.2/framework-arduino-avr-minicore-3.1.2.tar.gz","checksum":{"sha256":"3cc43553f35d2d00a277d488eefba628816104ae61a9ca9cecd60470f555c9f6"}}]},{"name":"2.2.2","files":[{"system":"*","download_url":"https://dl.registry.platformio.org/download/platformio/tool/framework-arduino-avr-minicore/2.2.2/framework-arduino-avr-minicore-2.2.2.tar.gz","checksum":{"sha256":"7172d1b1977237bcb996b61c12770ac3cc16ea422f0d44b2856b2d3a322c752e"}}]}]}"#; + let unavailable = parse_package_spec("framework-arduino-avr-minicore@3.1.0").unwrap(); + assert!( + resolve_registry_json( + unavailable.registry().unwrap(), + PackageKind::Framework, + "linux_x86_64", + metadata + ) + .is_err() + ); +} diff --git a/crates/fbuild-core/tests/platformio_package_resolution.rs b/crates/fbuild-core/tests/platformio_package_resolution.rs index 17a65f824..35855f2d2 100644 --- a/crates/fbuild-core/tests/platformio_package_resolution.rs +++ b/crates/fbuild-core/tests/platformio_package_resolution.rs @@ -318,7 +318,6 @@ fn teensy_51_manifest_honors_explicit_framework_pin_offline() { Some("~1.110301.0") ); } - #[test] fn stm32_20_arduino_board_requirements_select_published_payloads_offline() { let platform = parse_package_spec("platformio/ststm32@20.0.0").unwrap(); diff --git a/crates/fbuild-library/assets/avr_frameworks.json b/crates/fbuild-library/assets/avr_frameworks.json index f281fc13b..3984c0f5f 100644 --- a/crates/fbuild-library/assets/avr_frameworks.json +++ b/crates/fbuild-library/assets/avr_frameworks.json @@ -52,6 +52,42 @@ "validation_path": "cores/MCUdude_corefiles/Arduino.h", "core_dir": "MCUdude_corefiles" }, + "MajorCore": { + "name": "majorcore", + "github": "MCUdude/MajorCore", + "url": "https://dl.registry.platformio.org/download/platformio/tool/framework-arduino-avr-majorcore/3.1.0/framework-arduino-avr-majorcore-3.1.0.tar.gz", + "version": "3.1.0", + "tag_prefix": "v", + "checksum": "99b606a1ef59ee3c8caed7c7a3778875a22b0af6fdfcc7f21890b2caeca662e6", + "validation_path": "cores/MajorCore/Arduino.h" + }, + "MegaCore": { + "name": "megacore", + "github": "MCUdude/MegaCore", + "url": "https://dl.registry.platformio.org/download/platformio/tool/framework-arduino-avr-megacore/3.1.0/framework-arduino-avr-megacore-3.1.0.tar.gz", + "version": "3.1.0", + "tag_prefix": "v", + "checksum": "b2daa8f3432141ce21557b419b91605275b9e5fdb5f49eb8b1d3aaca5ff256ed", + "validation_path": "cores/MegaCore/Arduino.h" + }, + "MicroCore": { + "name": "microcore", + "github": "MCUdude/MicroCore", + "url": "https://dl.registry.platformio.org/download/platformio/tool/framework-arduino-avr-microcore/2.5.2/framework-arduino-avr-microcore-2.5.2.tar.gz", + "version": "2.5.2", + "tag_prefix": "v", + "checksum": "9fd6d1074fac692e15e1f4cbfc7c7b0df7bfedcddfafccb39889c622b97ddc11", + "validation_path": "cores/MicroCore/Arduino.h" + }, + "MightyCore": { + "name": "mightycore", + "github": "MCUdude/MightyCore", + "url": "https://dl.registry.platformio.org/download/platformio/tool/framework-arduino-avr-mightycore/3.1.0/framework-arduino-avr-mightycore-3.1.0.tar.gz", + "version": "3.1.0", + "tag_prefix": "v", + "checksum": "adba55b2b6254974cce65a63ecb75c3407ac7140b095c32e930394f27d18030b", + "validation_path": "cores/MightyCore/Arduino.h" + }, "megatinycore": { "name": "megatinycore", "github": "SpenceKonde/megaTinyCore", @@ -79,6 +115,15 @@ "validation_path": "cores/arduino/Arduino.h", "core_dir": "arduino", "needs_arduino_api": true + }, + "dxcore": { + "name": "dxcore", + "github": "SpenceKonde/DxCore", + "url": "https://dl.registry.platformio.org/download/platformio/tool/framework-arduino-megaavr-dxcore/1.6.2/framework-arduino-megaavr-dxcore-1.6.2.tar.gz", + "version": "1.6.2", + "tag_prefix": "", + "checksum": "72a8cdff1dba8da9f7cabb18db0e8e9ef5f412bc68bb269e72cfa5ad1ab9f911", + "validation_path": "cores/dxcore/Arduino.h" } } } diff --git a/crates/fbuild-library/src/library/avr_framework.rs b/crates/fbuild-library/src/library/avr_framework.rs index e8cd93e86..39a39a246 100644 --- a/crates/fbuild-library/src/library/avr_framework.rs +++ b/crates/fbuild-library/src/library/avr_framework.rs @@ -17,6 +17,7 @@ const AVR_FRAMEWORKS_JSON: &str = include_str!("../../assets/avr_frameworks.json struct FrameworkEntry { name: String, github: String, + url: Option, version: String, tag_prefix: String, checksum: Option, @@ -43,6 +44,7 @@ fn load_registry() -> HashMap { for (core_name, entry) in frameworks { let name = entry["name"].as_str().unwrap_or("").to_string(); let github = entry["github"].as_str().unwrap_or("").to_string(); + let url = entry["url"].as_str().map(str::to_string); let version = entry["version"].as_str().unwrap_or("").to_string(); let tag_prefix = entry["tag_prefix"].as_str().unwrap_or("").to_string(); let checksum = entry["checksum"].as_str().map(|s| s.to_string()); @@ -55,6 +57,7 @@ fn load_registry() -> HashMap { FrameworkEntry { name, github, + url, version, tag_prefix, checksum, @@ -79,6 +82,15 @@ fn lookup_entry(core_name: &str) -> fbuild_core::Result { }) } +fn framework_url(entry: &FrameworkEntry) -> String { + entry.url.clone().unwrap_or_else(|| { + format!( + "https://github.com/{}/archive/refs/tags/{}{}.tar.gz", + entry.github, entry.tag_prefix, entry.version + ) + }) +} + /// Data-driven AVR framework manager. /// /// Resolves the correct Arduino framework for any AVR board core @@ -100,10 +112,7 @@ impl AvrFramework { /// The core name comes from the board JSON (e.g., "arduino", "tiny", "tinymodern"). pub fn for_core(core_name: &str, project_dir: &Path) -> fbuild_core::Result { let entry = lookup_entry(core_name)?; - let url = format!( - "https://github.com/{}/archive/refs/tags/{}{}.tar.gz", - entry.github, entry.tag_prefix, entry.version - ); + let url = framework_url(&entry); Ok(Self { base: PackageBase::new( @@ -139,10 +148,23 @@ impl AvrFramework { ovr: fbuild_config::PackageOverride, ) -> fbuild_core::Result { let entry = lookup_entry(core_name)?; - let url = format!( - "https://github.com/{}/archive/refs/tags/{}{}.tar.gz", - entry.github, entry.tag_prefix, entry.version - ); + let url = framework_url(&entry); + // PlatformIO repacks MiniCore with `cores/MiniCore`, while its + // upstream GitHub tag uses `cores/MCUdude_corefiles`. Preserve the + // GitHub/URL-override layout unless the resolved payload is the + // PlatformIO package archive. + let platformio_minicore = + core_name == "MiniCore" && ovr.url.contains("/tool/framework-arduino-avr-minicore/"); + let validation_path = if platformio_minicore { + "cores/MiniCore/Arduino.h".to_string() + } else { + entry.validation_path + }; + let core_dir_override = if platformio_minicore { + Some("MiniCore".to_string()) + } else { + entry.core_dir + }; Ok(Self { base: PackageBase::new( @@ -156,8 +178,8 @@ impl AvrFramework { ) .with_override(ovr), core_name: core_name.to_string(), - validation_path: entry.validation_path, - core_dir_override: entry.core_dir, + validation_path, + core_dir_override, needs_arduino_api: entry.needs_arduino_api, }) } @@ -403,6 +425,22 @@ mod tests { assert_eq!(entry.core_dir.as_deref(), Some("arduino")); } + #[test] + fn published_alternate_core_defaults_have_verified_archives() { + for (core, version) in [ + ("MajorCore", "3.1.0"), + ("MegaCore", "3.1.0"), + ("MicroCore", "2.5.2"), + ("MightyCore", "3.1.0"), + ("dxcore", "1.6.2"), + ] { + let entry = lookup_entry(core).unwrap(); + assert_eq!(entry.version, version, "{core}"); + assert!(framework_url(&entry).starts_with("https://dl.registry.platformio.org/")); + assert_eq!(entry.checksum.as_ref().map(String::len), Some(64)); + } + } + #[test] fn test_digispark_dtiny_registered() { let registry = load_registry(); @@ -428,33 +466,48 @@ mod tests { assert_eq!(entry.core_dir.as_deref(), Some("pro")); } - /// Tripwire: `MicroCore` (MCUdude/MicroCore, used by `attiny13` / - /// `attiny13a` board JSONs) is not yet wired into `avr_frameworks.json`. - /// Source issue FastLED/FastLED#581, tracker FastLED/fbuild#389. When - /// MicroCore lands in the registry, flip this assertion to - /// `is_ok()` and update the gap tracker in - /// `tests/platform/attiny13/README.md`. + /// MicroCore is used by the ATtiny13 board family (FastLED/fbuild#389). #[test] - fn test_microcore_gap_tracked() { - assert!( - lookup_entry("MicroCore").is_err(), - "MicroCore lookup unexpectedly succeeded — see FastLED/fbuild#389; \ - update test_microcore_gap_tracked and tests/platform/attiny13/README.md" - ); + fn test_microcore_framework_registered() { + let entry = lookup_entry("MicroCore").unwrap(); + assert_eq!(entry.validation_path, "cores/MicroCore/Arduino.h"); + assert!(entry.checksum.is_some()); } - /// Tripwire: `dxcore` (SpenceKonde/DxCore, used by the AVR-Dx family — - /// `AVR128DA*`, `AVR128DB*`, `AVR64DA*`, `AVR64DB*`, `AVR64DD*`, - /// `AVR32DA*`, `AVR32DB*`) is not yet wired into `avr_frameworks.json`. - /// Source issue FastLED/FastLED#1307, tracker FastLED/fbuild#389. When - /// DxCore lands in the registry, flip this assertion to `is_ok()` and - /// update the gap tracker in `tests/platform/avr128da64/README.md`. #[test] - fn test_dxcore_gap_tracked() { + fn platformio_minicore_uses_repacked_core_directory() { + let project = tempfile::tempdir().unwrap(); + let registry = AvrFramework::for_core_with_override( + "MiniCore", + project.path(), + fbuild_config::PackageOverride { + url: "https://dl.registry.platformio.org/download/platformio/tool/framework-arduino-avr-minicore/3.1.2/framework-arduino-avr-minicore-3.1.2.tar.gz".to_string(), + version: "3.1.2".to_string(), + checksum: None, + }, + ) + .unwrap(); + assert_eq!(registry.validation_path, "cores/MiniCore/Arduino.h"); + assert!( + registry + .get_core_dir("MiniCore") + .ends_with("cores/MiniCore") + ); + + let github = AvrFramework::for_core("MiniCore", project.path()).unwrap(); + assert_eq!(github.validation_path, "cores/MCUdude_corefiles/Arduino.h"); assert!( - lookup_entry("dxcore").is_err(), - "dxcore lookup unexpectedly succeeded — see FastLED/fbuild#389; \ - update test_dxcore_gap_tracked and tests/platform/avr128da64/README.md" + github + .get_core_dir("MiniCore") + .ends_with("cores/MCUdude_corefiles") ); } + + /// DxCore is used by the AVR-Dx family (FastLED/fbuild#389). + #[test] + fn test_dxcore_framework_registered() { + let entry = lookup_entry("dxcore").unwrap(); + assert_eq!(entry.validation_path, "cores/dxcore/Arduino.h"); + assert!(entry.checksum.is_some()); + } } diff --git a/crates/fbuild-toolchain/src/toolchain/avr.rs b/crates/fbuild-toolchain/src/toolchain/avr.rs index a8c2dfeb7..5afcf2215 100644 --- a/crates/fbuild-toolchain/src/toolchain/avr.rs +++ b/crates/fbuild-toolchain/src/toolchain/avr.rs @@ -35,6 +35,13 @@ impl AvrToolchain { } } + /// Use a resolved PlatformIO toolchain payload instead of the Arduino CDN default. + pub fn with_override(project_dir: &Path, ovr: fbuild_config::PackageOverride) -> Self { + let mut toolchain = Self::new(project_dir); + toolchain.base = toolchain.base.with_override(ovr); + toolchain + } + /// Create with an explicit cache root (for testing without env vars). #[cfg(test)] fn with_cache_root(project_dir: &Path, cache_root: &Path) -> Self { diff --git a/tests/platform/atmega8/README.md b/tests/platform/atmega8/README.md index 2a2385bde..fb2f526c8 100644 --- a/tests/platform/atmega8/README.md +++ b/tests/platform/atmega8/README.md @@ -1,3 +1,7 @@ # ATmega8 Test Project Minimal blink sketch for ATmega8 (MiniCore) build validation. + +`atmega8-minicore-registry` pins the published atmelavr 5.3.0 platform and +MiniCore 3.1.2 framework payload. The original `atmega8` environment keeps +the unpinned default for compatibility coverage. diff --git a/tests/platform/atmega8/platformio.ini b/tests/platform/atmega8/platformio.ini index 6837babf9..e65d46318 100644 --- a/tests/platform/atmega8/platformio.ini +++ b/tests/platform/atmega8/platformio.ini @@ -2,3 +2,9 @@ platform = atmelavr board = ATmega8 framework = arduino + +[env:atmega8-minicore-registry] +platform = atmelavr@5.3.0 +board = ATmega8 +framework = arduino +platform_packages = framework-arduino-avr-minicore@3.1.2 diff --git a/tests/platform/attiny13/README.md b/tests/platform/attiny13/README.md index e0626ed00..342a5cffc 100644 --- a/tests/platform/attiny13/README.md +++ b/tests/platform/attiny13/README.md @@ -4,26 +4,24 @@ Minimal ATtiny13 project used to track fbuild support state for the smallest classic ATtiny class. Source FastLED issue: FastLED/FastLED#581. fbuild tracker: FastLED/fbuild#389. -## Current fbuild status (2026-06-03) +## Current fbuild status (2026-09-27) - **Board metadata**: present (`crates/fbuild-config/assets/boards/json/attiny13.json`, `attiny13a.json`). Both declare `core = MicroCore`. -- **Framework registry**: `MicroCore` is NOT mapped in - `crates/fbuild-packages/assets/avr_frameworks.json`. The AVR - orchestrator will fail at `AvrFramework::for_core("MicroCore", ..)` - with "no AVR framework registered for core 'MicroCore'". +- **Framework registry**: `MicroCore` is mapped to a checksummed PlatformIO + archive in `crates/fbuild-library/assets/avr_frameworks.json`. Resolving the + framework is no longer the expected blocker; an end-to-end tiny-chip build + remains a separate validation step. - **FastLED pin map**: present (`src/platforms/avr/attiny/pins/fastpin_attiny.h` has an `__AVR_ATtiny13__` branch). ## What this fixture proves -This fixture intentionally does NOT `#include ` — the fbuild -framework-resolve step fails first, so adding FastLED would only mask the -real blocker. Once `MicroCore` is added to `avr_frameworks.json` (github = -`MCUdude/MicroCore`, validation_path = `cores/MicroCore/Arduino.h`), this -directory can be flipped to a real FastLED smoke build with a single edit. +This fixture intentionally does NOT `#include ` so it can first +validate MicroCore and toolchain integration without a separate FastLED +compatibility or flash-size failure masking it. ## Why a 1 KiB flash chip matters diff --git a/tests/platform/attiny1616/README.md b/tests/platform/attiny1616/README.md index a4026a7f8..77c584e10 100644 --- a/tests/platform/attiny1616/README.md +++ b/tests/platform/attiny1616/README.md @@ -1,3 +1,7 @@ # ATtiny1616 Test Project Minimal blink sketch for ATtiny1616 (megaTinyCore) build validation. + +`attiny1616_registry` pins megaAVR platform 1.10.0 and megaTinyCore 2.6.11. +This environment also exercises the platform builder's newer AVR-GCC +requirement for megaTinyCore. diff --git a/tests/platform/attiny1616/platformio.ini b/tests/platform/attiny1616/platformio.ini index 5901fe55e..6b7e30628 100644 --- a/tests/platform/attiny1616/platformio.ini +++ b/tests/platform/attiny1616/platformio.ini @@ -2,3 +2,9 @@ platform = atmelmegaavr board = ATtiny1616 framework = arduino + +[env:attiny1616_registry] +platform = atmelmegaavr@1.10.0 +board = ATtiny1616 +framework = arduino +platform_packages = framework-arduino-megaavr-megatinycore@2.6.11 diff --git a/tests/platform/attiny85/README.md b/tests/platform/attiny85/README.md index bb835a7d8..7262cd297 100644 --- a/tests/platform/attiny85/README.md +++ b/tests/platform/attiny85/README.md @@ -1,3 +1,6 @@ # ATtiny85 Test Project Minimal blink sketch for ATtiny85 (ATTinyCore) build validation. + +`attiny85_registry` pins the published atmelavr 5.3.0 platform and ATTinyCore +1.5.2 package to exercise registry alias resolution for an alternate core. diff --git a/tests/platform/attiny85/platformio.ini b/tests/platform/attiny85/platformio.ini index 877ba17c2..4ac7d7113 100644 --- a/tests/platform/attiny85/platformio.ini +++ b/tests/platform/attiny85/platformio.ini @@ -2,3 +2,9 @@ platform = atmelavr board = attiny85 framework = arduino + +[env:attiny85_registry] +platform = atmelavr@5.3.0 +board = attiny85 +framework = arduino +platform_packages = framework-arduino-avr-attiny@1.5.2 diff --git a/tests/platform/avr128da64/README.md b/tests/platform/avr128da64/README.md index 40b8164de..1d4d1fed6 100644 --- a/tests/platform/avr128da64/README.md +++ b/tests/platform/avr128da64/README.md @@ -4,17 +4,18 @@ Minimal AVR128DA64 project used to track fbuild support state for the AVR-Dx (DA / DB / DD) family. Source FastLED issue: FastLED/FastLED#1307. fbuild tracker: FastLED/fbuild#389. -## Current fbuild status (2026-06-03) +## Current fbuild status (2026-09-27) - **Board metadata**: present for the full AVR-Dx matrix (`crates/fbuild-config/assets/boards/json/AVR128DA*.json`, `AVR128DB*.json`, `AVR64DA*.json`, `AVR64DB*.json`, `AVR64DD*.json`, `AVR32DA*.json`, `AVR32DB*.json`, `AVR64DD14/20/28/32.json`). All entries declare `platform = atmelmegaavr` and `core = dxcore`. -- **Framework registry**: `dxcore` is NOT mapped in - `crates/fbuild-packages/assets/avr_frameworks.json`. The AVR - orchestrator will fail at `AvrFramework::for_core("dxcore", ..)` - with "no AVR framework registered for core 'dxcore'". +- **Framework registry**: `dxcore` is mapped to a checksummed PlatformIO + archive in `crates/fbuild-library/assets/avr_frameworks.json`. The + megaAVR adapter selects PlatformIO's newer AVR-GCC requirement for DxCore + when the platform version is pinned. The `avr128da64_registry` environment + completed a Linux smoke build; other hosts remain to be validated by CI. - **FastLED platform support**: NO `AVR_DA` / `AVR128DA*` / `__AVR_AVR128DA*__` branch in `src/platforms/avr/`. The user-supplied pin map in FastLED/FastLED#1307 has not been merged into @@ -22,17 +23,18 @@ FastLED/FastLED#1307. fbuild tracker: FastLED/fbuild#389. ## What this fixture proves -This fixture intentionally does NOT `#include ` — fbuild fails -at framework resolve first, and even if it didn't, FastLED would `#error` -on the missing platform support. Both gaps must close before this -directory can be flipped to a real FastLED smoke build. +This fixture intentionally does NOT `#include ` so it can validate +the fbuild-side framework/toolchain path. FastLED's AVR-Dx support remains +separate and may still reject a FastLED sketch. + +`avr128da64_registry` pins megaAVR platform 1.10.0 and DxCore 1.6.2, which +selects the platform builder's newer AVR-GCC package. ## Next steps (fbuild-side) -Add a `dxcore` entry to `avr_frameworks.json` (github = -`SpenceKonde/DxCore`, validation_path = `cores/dxcore/Arduino.h`, -core_dir = `dxcore`). Possibly also gate the megaTinyCore-style toolchain -on the newer AVR-LibC / GCC bundle that DxCore ships with. +Run the fixture as a real build on the remaining supported hosts and fix any +host-specific compiler/linker incompatibility independently of package +resolution. ## Next steps (FastLED-side) diff --git a/tests/platform/avr128da64/platformio.ini b/tests/platform/avr128da64/platformio.ini index f2cbc08a8..b768339fe 100644 --- a/tests/platform/avr128da64/platformio.ini +++ b/tests/platform/avr128da64/platformio.ini @@ -8,17 +8,22 @@ ; (`crates/fbuild-config/assets/boards/json/AVR128DA*.json`, ; `AVR128DB*.json`, `AVR64DA*.json`, `AVR64DB*.json`, `AVR64DD*.json`, ; `AVR32DA*.json`, `AVR32DB*.json`) — all declare `core = dxcore`. -; - Framework registry: `dxcore` is NOT mapped in -; `crates/fbuild-packages/assets/avr_frameworks.json`. The AVR -; orchestrator will fail at `AvrFramework::for_core("dxcore", ..)`. +; - Framework registry: `dxcore` is mapped to a verified PlatformIO archive +; in `crates/fbuild-library/assets/avr_frameworks.json`. ; - FastLED pin map: NO `AVR_DA` / `AVR128DA*` / `__AVR_AVR128DA*__` ; support in `src/platforms/avr/`. The user-supplied pin map in ; FastLED/FastLED#1307 has not been merged. ; -; Both fbuild (DxCore framework wiring) and FastLED (AVR-Dx pin map + -; HW SPI defs) need work before this fixture can build with FastLED. +; FastLED (AVR-Dx pin map + HW SPI defs) still needs work before this +; fixture can build with FastLED. [env:avr128da64] platform = atmelmegaavr board = AVR128DA64 framework = arduino + +[env:avr128da64_registry] +platform = atmelmegaavr@1.10.0 +board = AVR128DA64 +framework = arduino +platform_packages = framework-arduino-megaavr-dxcore@1.6.2 diff --git a/tests/platform/nano_every/README.md b/tests/platform/nano_every/README.md index 99815f5b4..de4a22109 100644 --- a/tests/platform/nano_every/README.md +++ b/tests/platform/nano_every/README.md @@ -1,3 +1,6 @@ # Nano Every Test Project Minimal blink sketch for Arduino Nano Every (megaAVR) build validation. + +`nano_every_registry` pins published megaAVR platform 1.10.0 and Arduino +megaAVR framework 1.8.8 to exercise generic registry-path provisioning. diff --git a/tests/platform/nano_every/platformio.ini b/tests/platform/nano_every/platformio.ini index 0f5197e64..4da50c803 100644 --- a/tests/platform/nano_every/platformio.ini +++ b/tests/platform/nano_every/platformio.ini @@ -2,3 +2,9 @@ platform = atmelmegaavr board = nano_every framework = arduino + +[env:nano_every_registry] +platform = atmelmegaavr@1.10.0 +board = nano_every +framework = arduino +platform_packages = framework-arduino-megaavr@1.8.8 diff --git a/tests/platform/uno/README.md b/tests/platform/uno/README.md new file mode 100644 index 000000000..db990d2b4 --- /dev/null +++ b/tests/platform/uno/README.md @@ -0,0 +1,5 @@ +# Arduino Uno test project + +The `uno` environment uses the existing fbuild defaults. `uno_registry` +pins the published atmelavr 5.3.0 platform and Arduino AVR 5.4.0 package to +exercise registry alias resolution with the standard AVR core. diff --git a/tests/platform/uno/platformio.ini b/tests/platform/uno/platformio.ini index 1760d3569..f6cd9818d 100644 --- a/tests/platform/uno/platformio.ini +++ b/tests/platform/uno/platformio.ini @@ -11,4 +11,10 @@ [env:uno] platform = atmelavr board = uno -framework = arduino \ No newline at end of file +framework = arduino + +[env:uno_registry] +platform = atmelavr@5.3.0 +board = uno +framework = arduino +platform_packages = framework-arduino-avr@5.4.0