diff --git a/crates/fbuild-build-mcu/src/ch32v/ch32v_compiler.rs b/crates/fbuild-build-mcu/src/ch32v/ch32v_compiler.rs index b18cd8f2..494f6067 100644 --- a/crates/fbuild-build-mcu/src/ch32v/ch32v_compiler.rs +++ b/crates/fbuild-build-mcu/src/ch32v/ch32v_compiler.rs @@ -270,7 +270,7 @@ impl Compiler for Ch32vCompiler { #[cfg(test)] mod tests { use super::*; - use crate::ch32v::mcu_config::{apply_board_isa, get_ch32v_config_for_mcu}; + use crate::ch32v::mcu_config::{get_ch32v_config_for_mcu, with_board_isa}; fn test_compiler() -> Ch32vCompiler { let mut defines = HashMap::new(); @@ -302,8 +302,11 @@ mod tests { #[test] fn test_common_flags_use_board_isa() { - let mut config = get_ch32v_config_for_mcu("ch32v203").unwrap(); - apply_board_isa(&mut config, Some("rv32imacxw"), Some("ilp32")); + let config = with_board_isa( + get_ch32v_config_for_mcu("ch32v203").unwrap(), + Some("rv32imacxw"), + Some("ilp32"), + ); let mut compiler = test_compiler(); compiler.mcu_config = config; let flags = compiler.c_flags(); diff --git a/crates/fbuild-build-mcu/src/ch32v/mcu_config.rs b/crates/fbuild-build-mcu/src/ch32v/mcu_config.rs index b2e6f300..1818a203 100644 --- a/crates/fbuild-build-mcu/src/ch32v/mcu_config.rs +++ b/crates/fbuild-build-mcu/src/ch32v/mcu_config.rs @@ -96,42 +96,67 @@ pub fn normalize_march(march: &str) -> String { normalized } -/// Apply board ISA and ABI values to compiler and linker flags. -pub fn apply_board_isa(config: &mut Ch32vMcuConfig, march: Option<&str>, mabi: Option<&str>) { - apply_board_isa_for_toolchain(config, march, mabi, "riscv-none-elf"); +/// The recipe with the board's ISA and ABI applied to compiler and linker +/// flags, for the xPack `riscv-none-elf` compiler. +pub fn with_board_isa( + config: Ch32vMcuConfig, + march: Option<&str>, + mabi: Option<&str>, +) -> Ch32vMcuConfig { + with_board_isa_for_toolchain(config, march, mabi, "riscv-none-elf") } -/// Preserve WCH's vendor ISA extensions for its own compiler; only the xPack -/// compiler requires the stripped/modernized `zicsr` spelling. -pub fn apply_board_isa_for_toolchain( - config: &mut Ch32vMcuConfig, +/// The recipe with the board's ISA and ABI applied to compiler and linker +/// flags, spelled for the compiler with `executable_prefix`. +pub fn with_board_isa_for_toolchain( + config: Ch32vMcuConfig, march: Option<&str>, mabi: Option<&str>, executable_prefix: &str, -) { - fn replace(flags: &mut [String], prefix: &str, value: &str) { - for flag in flags { - if flag.starts_with(prefix) { - *flag = format!("{prefix}{value}"); - } - } +) -> Ch32vMcuConfig { + let config = match march { + Some(march) => with_flag_value( + config, + "-march=", + &march_for_toolchain(march, executable_prefix), + ), + None => config, + }; + match mabi { + Some(mabi) => with_flag_value(config, "-mabi=", mabi), + None => config, } +} - if let Some(march) = march { - let normalized = if executable_prefix == "riscv-none-elf" { - normalize_march(march) - } else { - march.to_ascii_lowercase() - }; - replace(&mut config.compiler_flags.common, "-march=", &normalized); - replace(&mut config.linker_flags, "-march=", &normalized); - } - if let Some(mabi) = mabi { - replace(&mut config.compiler_flags.common, "-mabi=", mabi); - replace(&mut config.linker_flags, "-mabi=", mabi); +/// Preserve WCH's vendor ISA extensions for its own compiler; only the xPack +/// compiler requires the stripped/modernized `zicsr` spelling. +fn march_for_toolchain(march: &str, executable_prefix: &str) -> String { + if executable_prefix == "riscv-none-elf" { + normalize_march(march) + } else { + march.to_ascii_lowercase() } } +/// Set the value of every `prefix`-led compiler and linker flag. +fn with_flag_value(mut config: Ch32vMcuConfig, prefix: &str, value: &str) -> Ch32vMcuConfig { + let set = |flags: Vec| -> Vec { + flags + .into_iter() + .map(|flag| { + if flag.starts_with(prefix) { + format!("{prefix}{value}") + } else { + flag + } + }) + .collect() + }; + config.compiler_flags.common = set(config.compiler_flags.common); + config.linker_flags = set(config.linker_flags); + config +} + #[cfg(test)] mod tests { use super::*; @@ -146,9 +171,8 @@ mod tests { #[test] fn platformio_gcc8_preserves_wch_vendor_isa() { - let mut config = get_ch32v_config_for_mcu("ch32v003").unwrap(); - apply_board_isa_for_toolchain( - &mut config, + let config = with_board_isa_for_toolchain( + get_ch32v_config_for_mcu("ch32v003").unwrap(), Some("rv32ecxw"), Some("ilp32e"), "riscv-none-embed", @@ -169,9 +193,12 @@ mod tests { } #[test] - fn test_apply_board_isa_updates_compiler_and_linker() { - let mut config = get_ch32v_config_for_mcu("ch32v003").unwrap(); - apply_board_isa(&mut config, Some("rv32imacxw"), Some("ilp32")); + fn test_with_board_isa_updates_compiler_and_linker() { + let config = with_board_isa( + get_ch32v_config_for_mcu("ch32v003").unwrap(), + Some("rv32imacxw"), + Some("ilp32"), + ); assert!( config .compiler_flags @@ -193,10 +220,9 @@ mod tests { } #[test] - fn test_apply_board_isa_none_is_noop() { - let mut config = get_ch32v_config_for_mcu("ch32v003").unwrap(); - let before = config.clone(); - apply_board_isa(&mut config, None, None); + fn test_with_board_isa_none_is_noop() { + let before = get_ch32v_config_for_mcu("ch32v003").unwrap(); + let config = with_board_isa(before.clone(), None, None); assert_eq!(config.compiler_flags.common, before.compiler_flags.common); assert_eq!(config.linker_flags, before.linker_flags); } diff --git a/crates/fbuild-build-mcu/src/ch32v/orchestrator.rs b/crates/fbuild-build-mcu/src/ch32v/orchestrator.rs index b0c75bf0..59d5194e 100644 --- a/crates/fbuild-build-mcu/src/ch32v/orchestrator.rs +++ b/crates/fbuild-build-mcu/src/ch32v/orchestrator.rs @@ -289,10 +289,9 @@ impl BuildOrchestrator for Ch32vOrchestrator { ); // 7. Build include dirs + compiler - let mut mcu_config = super::mcu_config::get_ch32v_config_for_mcu(&series)?; let toolchain_prefix = toolchain.executable_prefix(); - super::mcu_config::apply_board_isa_for_toolchain( - &mut mcu_config, + let mcu_config = super::mcu_config::with_board_isa_for_toolchain( + super::mcu_config::get_ch32v_config_for_mcu(&series)?, selected_march, selected_mabi, &toolchain_prefix, diff --git a/crates/fbuild-build-mcu/src/ch32v/orchestrator_tests.rs b/crates/fbuild-build-mcu/src/ch32v/orchestrator_tests.rs index c8186cca..f5833fb2 100644 --- a/crates/fbuild-build-mcu/src/ch32v/orchestrator_tests.rs +++ b/crates/fbuild-build-mcu/src/ch32v/orchestrator_tests.rs @@ -38,9 +38,8 @@ fn explicit_board_isa_and_abi_override_selected_platform_defaults() { preferred_board_value(None, "board_build.march", Some("rv32ecxw"), Some("rv32ec")), Some("rv32ecxw") ); - let mut config = crate::ch32v::mcu_config::get_ch32v_config_for_mcu("ch32v003").unwrap(); - crate::ch32v::mcu_config::apply_board_isa_for_toolchain( - &mut config, + let config = crate::ch32v::mcu_config::with_board_isa_for_toolchain( + crate::ch32v::mcu_config::get_ch32v_config_for_mcu("ch32v003").unwrap(), preferred_board_value( Some(&env), "board_build.march",