diff --git a/Cargo.lock b/Cargo.lock index 8ad2e8d1..36b7f2fc 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -988,7 +988,7 @@ checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be" [[package]] name = "fbuild-bench-fastled-examples" -version = "2.5.36" +version = "2.5.37" dependencies = [ "fbuild-core", "fbuild-library-select", @@ -1002,7 +1002,7 @@ dependencies = [ [[package]] name = "fbuild-build" -version = "2.5.36" +version = "2.5.37" dependencies = [ "async-trait", "blake3", @@ -1039,7 +1039,7 @@ dependencies = [ [[package]] name = "fbuild-build-arm" -version = "2.5.36" +version = "2.5.37" dependencies = [ "async-trait", "blake3", @@ -1073,7 +1073,7 @@ dependencies = [ [[package]] name = "fbuild-build-engine" -version = "2.5.36" +version = "2.5.37" dependencies = [ "async-trait", "blake3", @@ -1107,7 +1107,7 @@ dependencies = [ [[package]] name = "fbuild-build-esp" -version = "2.5.36" +version = "2.5.37" dependencies = [ "async-trait", "blake3", @@ -1142,7 +1142,7 @@ dependencies = [ [[package]] name = "fbuild-build-mcu" -version = "2.5.36" +version = "2.5.37" dependencies = [ "async-trait", "blake3", @@ -1176,7 +1176,7 @@ dependencies = [ [[package]] name = "fbuild-cli" -version = "2.5.36" +version = "2.5.37" dependencies = [ "blake3", "clap", @@ -1208,7 +1208,7 @@ dependencies = [ [[package]] name = "fbuild-config" -version = "2.5.36" +version = "2.5.37" dependencies = [ "fbuild-core", "fbuild-paths", @@ -1223,7 +1223,7 @@ dependencies = [ [[package]] name = "fbuild-core" -version = "2.5.36" +version = "2.5.37" dependencies = [ "async-trait", "fs2", @@ -1252,7 +1252,7 @@ dependencies = [ [[package]] name = "fbuild-daemon" -version = "2.5.36" +version = "2.5.37" dependencies = [ "async-trait", "axum 0.7.9", @@ -1291,7 +1291,7 @@ dependencies = [ [[package]] name = "fbuild-deploy" -version = "2.5.36" +version = "2.5.37" dependencies = [ "async-trait", "espflash", @@ -1319,7 +1319,7 @@ dependencies = [ [[package]] name = "fbuild-header-scan" -version = "2.5.36" +version = "2.5.37" dependencies = [ "criterion", "fbuild-paths", @@ -1330,7 +1330,7 @@ dependencies = [ [[package]] name = "fbuild-library" -version = "2.5.36" +version = "2.5.37" dependencies = [ "async-trait", "axum 0.7.9", @@ -1362,7 +1362,7 @@ dependencies = [ [[package]] name = "fbuild-library-select" -version = "2.5.36" +version = "2.5.37" dependencies = [ "bincode", "blake3", @@ -1383,7 +1383,7 @@ dependencies = [ [[package]] name = "fbuild-packages" -version = "2.5.36" +version = "2.5.37" dependencies = [ "async-trait", "axum 0.7.9", @@ -1415,7 +1415,7 @@ dependencies = [ [[package]] name = "fbuild-packages-fetch" -version = "2.5.36" +version = "2.5.37" dependencies = [ "async-trait", "axum 0.7.9", @@ -1444,7 +1444,7 @@ dependencies = [ [[package]] name = "fbuild-paths" -version = "2.5.36" +version = "2.5.37" dependencies = [ "blake3", "fbuild-core", @@ -1456,7 +1456,7 @@ dependencies = [ [[package]] name = "fbuild-python" -version = "2.5.36" +version = "2.5.37" dependencies = [ "base64", "fbuild-core", @@ -1480,7 +1480,7 @@ dependencies = [ [[package]] name = "fbuild-serial" -version = "2.5.36" +version = "2.5.37" dependencies = [ "async-trait", "base64", @@ -1503,7 +1503,7 @@ dependencies = [ [[package]] name = "fbuild-test-support" -version = "2.5.36" +version = "2.5.37" dependencies = [ "fbuild-config", "fbuild-core", @@ -1523,7 +1523,7 @@ dependencies = [ [[package]] name = "fbuild-toolchain" -version = "2.5.36" +version = "2.5.37" dependencies = [ "async-trait", "axum 0.7.9", diff --git a/Cargo.toml b/Cargo.toml index 59d4c574..6e6dd725 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -93,7 +93,7 @@ targets = [ ] [workspace.package] -version = "2.5.36" +version = "2.5.37" edition = "2021" rust-version = "1.95.0" license = "AGPL-3.0-only" diff --git a/crates/fbuild-build-esp/src/esp32/fixups.rs b/crates/fbuild-build-esp/src/esp32/fixups.rs index 83a70958..3f846523 100644 --- a/crates/fbuild-build-esp/src/esp32/fixups.rs +++ b/crates/fbuild-build-esp/src/esp32/fixups.rs @@ -20,16 +20,20 @@ type Rule = fn(Esp32McuConfig) -> Esp32McuConfig; /// Adapt the recipe to the selected toolchain package. /// -/// - GCC < 14: the paired SDKs (pioarduino 51.x/53.x, Arduino 3.0/3.1) do not -/// define `__dso_handle` for `-fuse-cxa-atexit`-generated references, on -/// Xtensa and RISC-V alike. +/// - GCC < 14, and ESP32-C2/H2 with GCC 14: the paired SDKs do not define +/// `__dso_handle` for `-fuse-cxa-atexit`-generated references. /// - Per-MCU Xtensa packages (GCC 8 and 12) reject the atomics switch. /// - Per-MCU Xtensa GCC 8 (official `espressif32` 6.x/7.x) needs its own /// linker recipe, older language standards, and no LTO. pub fn for_toolchain(config: Esp32McuConfig, toolchain: &PackageInfo) -> Esp32McuConfig { let legacy_xtensa32 = toolchain.name == "toolchain-xtensa32"; let per_mcu_xtensa = is_per_mcu_xtensa(&toolchain.name) || legacy_xtensa32; - let config = apply_if(is_before_gcc14(&toolchain.version), config, drop_cxa_atexit); + let lacks_dso_handle = matches!(config.mcu.as_str(), "esp32c2" | "esp32h2"); + let config = apply_if( + is_before_gcc14(&toolchain.version) || lacks_dso_handle, + config, + drop_cxa_atexit, + ); let config = apply_if(per_mcu_xtensa, config, drop_hardware_atomics); let config = apply_if( (per_mcu_xtensa && is_gcc8(&toolchain.version)) || legacy_xtensa32, @@ -255,6 +259,20 @@ mod tests { } } + #[test] + fn esp32c2_h2_sdk_drops_cxa_atexit_on_gcc14() { + for mcu in ["esp32c2", "esp32h2"] { + let config = for_toolchain( + get_mcu_config(mcu).unwrap(), + &toolchain("toolchain-riscv32-esp", "14.2.0+20241119"), + ); + assert!( + !has(&config.compiler_flags.cxx, "-fuse-cxa-atexit"), + "{mcu} kept -fuse-cxa-atexit without __dso_handle" + ); + } + } + #[test] fn unparseable_version_keeps_recipe() { // pioarduino 55.x URL toolchain: version is not a bare GCC version. diff --git a/crates/fbuild-library/src/library/esp32_framework/libs.rs b/crates/fbuild-library/src/library/esp32_framework/libs.rs index 6de8cff8..e39b759c 100644 --- a/crates/fbuild-library/src/library/esp32_framework/libs.rs +++ b/crates/fbuild-library/src/library/esp32_framework/libs.rs @@ -118,6 +118,29 @@ fn merge_skeleton_mcu_entries( } fn patch_mcu_compatibility(mcu_dir: &Path, mcu: &str) -> fbuild_core::Result<()> { + if matches!(mcu, "esp32c2" | "esp32h2") { + // The packaged esp_bt.h uses ../../../../controller//esp_bt_cfg.h, + // which resolves to include/controller/. The package places the + // actual header under include/bt/controller/ instead. + let source = mcu_dir + .join("include") + .join("bt") + .join("controller") + .join(mcu) + .join("esp_bt_cfg.h"); + let expected = mcu_dir + .join("include") + .join("controller") + .join(mcu) + .join("esp_bt_cfg.h"); + if source.exists() && !expected.exists() { + if let Some(parent) = expected.parent() { + std::fs::create_dir_all(parent)?; + } + std::fs::copy(source, expected)?; + } + } + if mcu != "esp32c2" { return Ok(()); } @@ -165,6 +188,7 @@ impl Esp32Framework { // (esp32-arduino-libs/) layouts. for mcu_dir in mcu_sdk_dir_candidates(&tools_dir, mcu) { if mcu_sdk_complete(&mcu_dir) { + patch_mcu_compatibility(&mcu_dir, mcu)?; return Ok(()); } } @@ -216,6 +240,13 @@ impl Esp32Framework { merge_sdk_archive_entries(temp_dir.path(), &tools_dir)?; + for mcu_dir in mcu_sdk_dir_candidates(&tools_dir, mcu) { + if mcu_sdk_complete(&mcu_dir) { + patch_mcu_compatibility(&mcu_dir, mcu)?; + break; + } + } + tracing::info!("ESP32 SDK libs installed"); Ok(()) } @@ -413,6 +444,45 @@ mod tests { ); } + fn assert_bluetooth_controller_header_compatible(mcu: &str) { + let tmp = tempfile::TempDir::new().unwrap(); + let mcu_dir = tmp.path().join(mcu); + let source = mcu_dir + .join("include") + .join("bt") + .join("controller") + .join(mcu) + .join("esp_bt_cfg.h"); + let expected = mcu_dir + .join("include") + .join("controller") + .join(mcu) + .join("esp_bt_cfg.h"); + write(&source, "// packaged Bluetooth controller config\n"); + + patch_mcu_compatibility(&mcu_dir, mcu).unwrap(); + + assert_eq!( + std::fs::read_to_string(&expected).unwrap(), + "// packaged Bluetooth controller config\n" + ); + patch_mcu_compatibility(&mcu_dir, mcu).unwrap(); + assert_eq!( + std::fs::read_to_string(&expected).unwrap(), + std::fs::read_to_string(&source).unwrap() + ); + } + + #[test] + fn esp32c2_packaged_bluetooth_header_resolves_relative_include() { + assert_bluetooth_controller_header_compatible("esp32c2"); + } + + #[test] + fn esp32h2_packaged_bluetooth_header_resolves_relative_include() { + assert_bluetooth_controller_header_compatible("esp32h2"); + } + #[test] fn patch_mcu_compatibility_leaves_other_mcus_untouched() { let tmp = tempfile::TempDir::new().unwrap(); diff --git a/pyproject.toml b/pyproject.toml index 9483d6e0..5789b19a 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "fbuild" -version = "2.5.36" +version = "2.5.37" description = "PlatformIO-compatible embedded build tool (Rust implementation)" readme = "README.md" license = "AGPL-3.0-only"