Skip to content
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
56 changes: 56 additions & 0 deletions crates/fbuild-build-esp/src/esp32/orchestrator/packages.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,13 @@ pub(super) async fn resolve_pioarduino_packages(
// Ensure pioarduino platform (contains platform.json with metadata URLs).
let platform = pioarduino_platform(project_dir, env_config);
fbuild_packages::Package::ensure_installed(&platform).await?;
let platform = if legacy_toolchain_pin(&platform, env_config, mcu_config.is_riscv()) {
let stable = fbuild_packages::library::Esp32Platform::new(project_dir);
fbuild_packages::Package::ensure_installed(&stable).await?;
stable
} else {
platform
};

// Resolve toolchain via metadata
let toolchain = resolve_and_create_toolchain(&platform, project_dir, mcu_config)?;
Expand Down Expand Up @@ -132,6 +139,19 @@ pub(crate) async fn provision_esp32(
// Every other package is named by the platform's platform.json.
return Ok(rows);
}
// Provision what the build will actually use (see `legacy_toolchain_pin`).
let platform = if legacy_toolchain_pin(&platform, env_config, mcu_config.is_riscv()) {
let stable = fbuild_packages::library::Esp32Platform::new(project_dir);
let stable_row = provision_package(PackageKind::Platform, &stable, mode).await;
let stable_ready = is_installed(&stable_row);
rows.push(stable_row);
if !stable_ready {
return Ok(rows);
}
stable
} else {
platform
};

rows.push(provision_toolchain(&platform, project_dir, &mcu_config, mode).await);

Expand Down Expand Up @@ -255,6 +275,42 @@ async fn ensure_sdk_libs(
Ok(())
}

/// True when an honored `platform` pin predates the unified ESP32 toolchain
/// and the build must fall back to the pioarduino stable platform.
///
/// #1432 started honoring `platform = <release URL>`. Releases before the
/// unified toolchain (pioarduino 51.x, arduino-esp32 3.0) name per-MCU
/// registry packages (`toolchain-xtensa-esp32s3@12.2.0+20230208`) that toolchain
/// resolution cannot read, so it fell through to legacy hardcoded URLs that
/// 404 and failed the build outright. Until per-MCU registry toolchains are
/// supported, such a pin warns and builds against stable -- exactly what
/// every release before #1432 did with it.
fn legacy_toolchain_pin(
platform: &fbuild_packages::library::Esp32Platform,
env_config: Option<&HashMap<String, String>>,
is_riscv: bool,
) -> bool {
let pinned = env_config
.and_then(|env| {
crate::package_override::resolve_platform_override(env, "platform-espressif32")
})
.is_some();
if !pinned || platform.has_unified_toolchain(is_riscv) {
return false;
}
let pin = env_config
.and_then(|env| env.get("platform"))
.map(|p| p.trim())
.unwrap_or("the pinned platform");
tracing::warn!(
"platform pin `{pin}` predates the unified ESP32 toolchain (its platform.json has no \
toolchain metadata URL for this MCU) and fbuild cannot provision its per-MCU registry \
toolchain yet; building with the pioarduino stable platform instead, as fbuild did \
before it honored platform pins"
);
true
}

/// Name a `platform` pin fbuild cannot honor instead of dropping it silently
/// (FastLED/fbuild#1407). Registry pins and git URLs fall back to the
/// pioarduino stable platform, which carries a different framework release.
Expand Down
44 changes: 44 additions & 0 deletions crates/fbuild-library/src/library/esp32_platform.rs
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,20 @@ impl Esp32Platform {
self.get_package_url(package_name)
}

/// Whether this platform names the MCU-primary toolchain by a metadata
/// URL -- the unified `toolchain-xtensa-esp-elf` / `toolchain-riscv32-esp`
/// scheme that toolchain resolution understands.
///
/// Older pioarduino releases (e.g. 51.03.04) name per-MCU registry
/// packages instead (`toolchain-xtensa-esp32s3@12.2.0+20230208`), and
/// their `toolchain-riscv32-esp` entry is a registry version, not a URL.
pub fn has_unified_toolchain(&self, is_riscv: bool) -> bool {
matches!(
self.get_toolchain_metadata_url(is_riscv),
Ok(url) if url.starts_with("https://") || url.starts_with("http://")
)
}

/// Read and parse the `packages` section of `platform.json`.
///
/// Shared between [`Self::get_package_url`] and
Expand Down Expand Up @@ -395,4 +409,34 @@ mod tests {
"wrong error: {err}"
);
}

/// pioarduino `platform-espressif32@51.03.04` (arduino-esp32 3.0) predates
/// the unified toolchain: per-MCU registry packages, and a
/// `toolchain-riscv32-esp` entry that is a registry version, not a URL.
const PIOARDUINO_51_03_04_PACKAGES_FRAGMENT: &str = r#"{
"packages": {
"toolchain-xtensa-esp32s3": { "type": "toolchain", "owner": "espressif", "version": "12.2.0+20230208" },
"toolchain-riscv32-esp": { "type": "toolchain", "owner": "espressif", "version": "12.2.0+20230208" }
}
}"#;

#[test]
fn test_has_unified_toolchain_for_pioarduino_54_03_20() {
let tmp = tempfile::TempDir::new().unwrap();
write_platform_json(tmp.path(), PIOARDUINO_54_03_20_PACKAGES_FRAGMENT);
let p = platform_with_install_dir(tmp.path());
assert!(p.has_unified_toolchain(false));
assert!(p.has_unified_toolchain(true));
}

#[test]
fn test_no_unified_toolchain_for_legacy_pioarduino_51_03_04() {
let tmp = tempfile::TempDir::new().unwrap();
write_platform_json(tmp.path(), PIOARDUINO_51_03_04_PACKAGES_FRAGMENT);
let p = platform_with_install_dir(tmp.path());
// Xtensa: no `toolchain-xtensa-esp-elf` entry at all.
assert!(!p.has_unified_toolchain(false));
// RISC-V: the entry exists but names a registry version, not a URL.
assert!(!p.has_unified_toolchain(true));
}
}
Loading