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
36 changes: 36 additions & 0 deletions crates/fbuild-config/src/board/loaders.rs
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,40 @@ fn resolve_max_flash(
})
}

fn parse_monitor_filters(value: &str) -> Vec<String> {
let trimmed = value.trim();
if trimmed.is_empty() || trimmed == "[]" {
return Vec::new();
}

trimmed
.lines()
.flat_map(|line| line.split(','))
.map(str::trim)
.filter(|filter| !filter.is_empty())
.map(ToString::to_string)
.collect()
}

fn resolve_monitor_filters(
overrides: &HashMap<String, String>,
defaults: &HashMap<String, String>,
is_esp32_family: bool,
) -> Option<Vec<String>> {
overrides
.get("monitor_filters")
.map(|value| parse_monitor_filters(value))
.or_else(|| {
defaults
.get("monitor_filters")
.map(|value| parse_monitor_filters(value))
})
.or_else(|| {
is_esp32_family
.then(|| vec!["default".to_string(), "esp32_exception_decoder".to_string()])
})
}

impl BoardConfig {
/// Load board config from a boards.txt file.
///
Expand Down Expand Up @@ -141,6 +175,7 @@ impl BoardConfig {
upload_protocol: get("upload.protocol")
.or_else(|| props.get("upload.protocol").cloned()),
upload_speed: get("upload.speed").or_else(|| props.get("upload.speed").cloned()),
monitor_filters: resolve_monitor_filters(overrides, &props, is_esp32_family),
max_flash: resolve_max_flash(overrides, &props),
max_ram: get("maximum_data_size")
.or_else(|| props.get("maximum_data_size").cloned())
Expand Down Expand Up @@ -308,6 +343,7 @@ impl BoardConfig {
.get("upload.speed")
.cloned()
.or_else(|| defaults.get("upload.speed").cloned()),
monitor_filters: resolve_monitor_filters(overrides, &defaults, is_esp32_family),
max_flash: resolve_max_flash(overrides, &defaults),
max_ram: overrides
.get("maximum_data_size")
Expand Down
8 changes: 8 additions & 0 deletions crates/fbuild-config/src/board/methods.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,14 @@ impl BoardConfig {
&& EMULATOR_TOOL_NAMES.contains(&tool_name)
}

/// PlatformIO `monitor_filters` value to emit for this board.
pub fn monitor_filters_ini_value(&self) -> Option<String> {
self.monitor_filters
.as_ref()
.filter(|filters| !filters.is_empty())
.map(|filters| filters.join(", "))
}

/// Resolve the effective ESP32 SDK memory profile used for variant headers/libs.
///
/// This keeps the SDK `sdkconfig.h` and memory-profile libraries aligned
Expand Down
42 changes: 42 additions & 0 deletions crates/fbuild-config/src/board/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -283,6 +283,48 @@ fn test_platform_detection() {
assert_eq!(rpi.platform(), Some(fbuild_core::Platform::RaspberryPi));
}

#[test]
fn test_non_esp32_monitor_filters_default_absent() {
let config = BoardConfig::from_board_id("uno", &HashMap::new()).unwrap();
assert_eq!(config.monitor_filters, None);
assert_eq!(config.monitor_filters_ini_value(), None);
}

#[test]
fn test_custom_monitor_filters_emit_in_platformio_format() {
let mut overrides = HashMap::new();
overrides.insert(
"monitor_filters".to_string(),
"default, time, log2file".to_string(),
);

let config = BoardConfig::from_board_id("uno", &overrides).unwrap();

assert_eq!(
config.monitor_filters,
Some(vec![
"default".to_string(),
"time".to_string(),
"log2file".to_string()
])
);
assert_eq!(
config.monitor_filters_ini_value(),
Some("default, time, log2file".to_string())
);
}

#[test]
fn test_empty_monitor_filters_suppresses_emit() {
let mut overrides = HashMap::new();
overrides.insert("monitor_filters".to_string(), "[]".to_string());

let config = BoardConfig::from_board_id("esp32dev", &overrides).unwrap();

assert_eq!(config.monitor_filters, Some(Vec::new()));
assert_eq!(config.monitor_filters_ini_value(), None);
}

#[test]
fn test_parse_boards_txt_with_comments() {
let props = parse_boards_txt(
Expand Down
17 changes: 17 additions & 0 deletions crates/fbuild-config/src/board/tests_enriched_json.rs
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,23 @@ fn test_esp32dev_enriched_fields() {
assert_eq!(config.upload_speed, Some("460800".to_string()));
}

#[test]
fn test_esp32dev_defaults_monitor_filters() {
let config = BoardConfig::from_board_id("esp32dev", &HashMap::new()).unwrap();

assert_eq!(
config.monitor_filters,
Some(vec![
"default".to_string(),
"esp32_exception_decoder".to_string()
])
);
assert_eq!(
config.monitor_filters_ini_value(),
Some("default, esp32_exception_decoder".to_string())
);
}

#[test]
fn test_esp32_flash_mode_env_override_honoured() {
// The user can opt back into QIO via `board_build.flash_mode = qio`
Expand Down
6 changes: 6 additions & 0 deletions crates/fbuild-config/src/board/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,12 @@ pub struct BoardConfig {
pub upload_protocol: Option<String>,
/// Upload speed
pub upload_speed: Option<String>,
/// PlatformIO serial monitor filters.
///
/// ESP32-family boards default to `default, esp32_exception_decoder` when
/// unset. An explicit empty list in project config suppresses that default.
#[serde(default, skip_serializing_if = "Option::is_none")]
pub monitor_filters: Option<Vec<String>>,
/// Maximum flash size in bytes
pub max_flash: Option<u64>,
/// Maximum RAM size in bytes
Expand Down
2 changes: 2 additions & 0 deletions crates/fbuild-config/src/ini_parser/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -348,6 +348,8 @@ impl PlatformIOConfig {
overrides.insert(stripped.to_string(), value.clone());
} else if let Some(stripped) = key.strip_prefix("board_upload.") {
overrides.insert(format!("upload.{}", stripped), value.clone());
} else if key == "monitor_filters" {
overrides.insert(key.clone(), value.clone());
}
}

Expand Down
22 changes: 22 additions & 0 deletions crates/fbuild-config/src/ini_parser/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -750,6 +750,28 @@ board_upload.flash_size = 4MB
assert_eq!(overrides.get("upload.flash_size"), Some(&"4MB".to_string()));
}

#[test]
fn test_get_board_overrides_preserves_monitor_filters() {
let f = write_ini(
"\
[env:esp32dev]
platform = espressif32
board = esp32dev
framework = arduino
monitor_filters =
default
esp32_exception_decoder
",
);
let config = PlatformIOConfig::from_path(f.path()).unwrap();
let overrides = config.get_board_overrides("esp32dev").unwrap();

assert_eq!(
overrides.get("monitor_filters"),
Some(&"default\nesp32_exception_decoder".to_string())
);
}

#[test]
fn test_get_source_filter_prefers_build_src_filter() {
let f = write_ini(
Expand Down
2 changes: 2 additions & 0 deletions docs/reference/platformio-ini.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ board = uno
framework = arduino
upload_port = COM3
monitor_speed = 9600
monitor_filters = default, esp32_exception_decoder
build_flags =
-DDEBUG
-DLED_PIN=13
Expand All @@ -48,6 +49,7 @@ Common keys:
| `[env:<name>] framework` | Framework, usually `arduino`. |
| `upload_port` | Preferred deploy port. |
| `monitor_speed` | Serial monitor baud rate. |
| `monitor_filters` | Serial monitor filters. ESP32-family boards default to `default, esp32_exception_decoder` when unset; use `monitor_filters = []` to suppress. |
| `build_flags` | Extra compiler flags. |
| `lib_deps` | Library dependencies, including GitHub URLs. |
| `build_type` | Build profile; `debug` preserves unwind metadata. |
Expand Down
Loading