Skip to content

Add native PlatformIO source filters and debug flag support#44

Merged
zackees merged 1 commit intomainfrom
feat/native-source-filter-tdd
Apr 14, 2026
Merged

Add native PlatformIO source filters and debug flag support#44
zackees merged 1 commit intomainfrom
feat/native-source-filter-tdd

Conversation

@zackees
Copy link
Copy Markdown
Member

@zackees zackees commented Apr 14, 2026

Summary

  • add native build_src_filter / src_filter support and apply it to sketch source discovery across native orchestrators
  • add native handling for build_unflags, build_type=debug, and debug_build_flags in the build pipeline
  • extend the extra-scripts runtime with small deterministic shims used by sampled PlatformIO repos, including Dump, BoardConfig(), and PioPlatform()

Testing

  • cargo test -p fbuild-config --lib
  • cargo test -p fbuild-build --lib

Closes #43

Summary by CodeRabbit

Release Notes

  • New Features

    • Added source filtering support during builds to selectively include/exclude sketch sources based on configurable patterns.
    • Added debug build type support with automatic flag injection and configuration.
    • Added build unflags configuration to remove specified compiler/linker flags.
    • Extended build configuration options for platform-specific settings.
  • Documentation

    • Expanded script runtime capabilities with board configuration and platform information access.

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Apr 14, 2026

📝 Walkthrough

Walkthrough

This PR extends native platformio.ini compatibility by implementing source filtering via src_filter/build_src_filter, unflag removal via build_unflags, debug build type support, and enriched script runtime APIs. All twelve architecture-specific orchestrators are updated to apply source filters during discovery.

Changes

Cohort / File(s) Summary
Source Filtering Infrastructure
crates/fbuild-build/src/source_scanner.rs, crates/fbuild-config/src/ini_parser.rs
Added rule-based source filtering with regex-based include/exclude patterns; exposed scan_sketch_sources_filtered() and scan_all_filtered() APIs; added config getters for build_unflags, build_type, debug_build_flags, and source_filter.
Build Pipeline & Debug Support
crates/fbuild-build/src/pipeline.rs
Extended BuildContext with source_filter field; implemented debug build type handling with apply_debug_build_type(), unflag removal via apply_build_unflags(), and corresponding unit tests.
Orchestrator Source Filter Integration
crates/fbuild-build/src/apollo3/orchestrator.rs, crates/fbuild-build/src/avr/orchestrator.rs, crates/fbuild-build/src/ch32v/orchestrator.rs, crates/fbuild-build/src/esp32/orchestrator.rs, crates/fbuild-build/src/esp8266/orchestrator.rs, crates/fbuild-build/src/nrf52/orchestrator.rs, crates/fbuild-build/src/renesas/orchestrator.rs, crates/fbuild-build/src/rp2040/orchestrator.rs, crates/fbuild-build/src/sam/orchestrator.rs, crates/fbuild-build/src/silabs/orchestrator.rs, crates/fbuild-build/src/stm32/orchestrator.rs, crates/fbuild-build/src/teensy/orchestrator.rs
Updated all orchestrators to pass ctx.source_filter.as_deref() to scanner methods, applying source filtering during source discovery.
Script Runtime Shims
crates/fbuild-build/src/script_runtime.rs, crates/fbuild-build/src/script_runtime_harness.py
Added build_script_runtime_board_config() to expose board-related metadata (MCU, F_CPU, flash, memory, etc.) to extra scripts; extended MockEnv with BoardConfig(), PioPlatform(), Dump(), IsCleanTarget(), IsIntegrationDump(), Flatten(), VerboseAction(), and Execute() methods; added Python-runtime integration tests validating board/platform shim access.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

Poem

🐰 Hops through filters with glee
Debug flags bloom on the tree
Unflags swept clean
Scripts now convene
With board and platform they see!

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The PR title accurately summarizes the main change: adding native PlatformIO source filters and debug flag support across the codebase.
Linked Issues check ✅ Passed The PR implements all prioritized coding objectives from issue #43: native source filtering support (#1), build_unflags support (#2), build_type=debug and debug_build_flags support (#3), and limited script API shims (#4).
Out of Scope Changes check ✅ Passed All changes are directly aligned with the linked issue objectives: source filter implementation, flag handling, debug build support, and extra-scripts shims; no unrelated modifications detected.
Docstring Coverage ✅ Passed Docstring coverage is 87.65% which is sufficient. The required threshold is 80.00%.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/native-source-filter-tdd

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (3)
crates/fbuild-build/src/pipeline.rs (1)

235-253: Consider edge case: -ggdb without level suffix.

The is_platformio_debug_cleanup_flag function handles -ggdb[0-3] (6-character strings) but doesn't handle bare -ggdb (5 characters). PlatformIO's default debug flags include -ggdb2, so this may not matter in practice, but if a user specifies -ggdb without a level, it won't be cleaned up before adding the debug flags.

Similarly, is_platformio_debug_link_flag uses flag.starts_with("-g") which would match -ggdb, but the cleanup function wouldn't remove it.

This is a minor edge case that's unlikely to cause issues in practice.

♻️ Optional: Handle bare `-ggdb` in cleanup
 fn is_platformio_debug_cleanup_flag(flag: &str) -> bool {
     if flag == "-Os" || flag == "-g" {
         return true;
     }
+    if flag == "-ggdb" {
+        return true;
+    }
     if flag.len() == 3 {
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@crates/fbuild-build/src/pipeline.rs` around lines 235 - 253, The cleanup
logic in is_platformio_debug_cleanup_flag misses the bare "-ggdb" (5 chars)
case; update is_platformio_debug_cleanup_flag (and only that function) to treat
"-ggdb" as a cleanup flag in addition to "-ggdb[0-3]" — e.g. accept either a
5-char exact "-ggdb" or a 6-char "-ggdbN" where N ∈ {0,1,2,3}; leave
is_platformio_debug_link_flag as-is so it continues to match "-g" and "-ggdb"
during linking.
crates/fbuild-build/src/source_scanner.rs (2)

61-71: Consider adding doc comments explaining the matching semantics.

These structs implement PlatformIO-style source filtering, but the behavior isn't documented. The has_include_rules field particularly affects default matching behavior in a non-obvious way—when include rules exist, unmatched files are excluded; otherwise, they're included by default.

📝 Suggested documentation
+/// PlatformIO-style source filter for selective file inclusion/exclusion.
+///
+/// Rules are evaluated in order; the last matching rule determines inclusion.
+/// If any `+<pattern>` rules exist, files not matching any rule are excluded by default.
+/// If only `-<pattern>` rules exist, files are included unless explicitly excluded.
 #[derive(Debug)]
 struct SourceFilter {
     rules: Vec<SourceFilterRule>,
+    /// When true, unmatched files are excluded by default
     has_include_rules: bool,
 }
 
+/// A single include (+) or exclude (-) rule with a compiled regex matcher.
 #[derive(Debug)]
 struct SourceFilterRule {
     include: bool,
     matcher: Regex,
 }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@crates/fbuild-build/src/source_scanner.rs` around lines 61 - 71, Add doc
comments to SourceFilter and SourceFilterRule describing their PlatformIO-style
matching semantics: explain that SourceFilter.rules is a list of
SourceFilterRule entries, each rule's include boolean indicates whether matching
paths are allowed (include=true) or denied (include=false), and matcher (Regex)
is used to test paths; clarify that SourceFilter.has_include_rules toggles the
default for unmatched files — if any include rules exist unmatched files are
excluded, otherwise unmatched files are included by default. Place these
comments above the struct definitions for SourceFilter and SourceFilterRule to
make the behavior explicit to future readers.

781-812: Good foundational tests; consider expanding coverage.

The tests validate the core functionality well. For robustness, consider adding tests for:

  • Glob wildcards: **, ?, *.cpp
  • Patterns containing regex-special characters (., +)
  • Error cases (malformed patterns like +<>, +< >, foo)
  • Windows-style backslash patterns as input
🧪 Example additional test
#[test]
fn test_source_filter_glob_wildcards() {
    let (_tmp, src_dir, build_dir) = setup_project(&[
        ("foo.cpp", ""),
        ("bar.cpp", ""),
        ("sub/baz.cpp", ""),
    ]);
    let scanner = SourceScanner::new(&src_dir, &build_dir);
    // Test *.cpp pattern matches all .cpp files
    let sources = scanner
        .scan_sketch_sources_filtered(Some("+<*.cpp>"))
        .unwrap();
    assert_eq!(sources.len(), 3);
}

#[test]
fn test_source_filter_invalid_pattern_error() {
    let (_tmp, src_dir, build_dir) = setup_project(&[("main.cpp", "")]);
    let scanner = SourceScanner::new(&src_dir, &build_dir);
    let result = scanner.scan_sketch_sources_filtered(Some("invalid"));
    assert!(result.is_err());
}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@crates/fbuild-build/src/source_scanner.rs` around lines 781 - 812, Add unit
tests expanding coverage for SourceScanner::scan_sketch_sources_filtered: create
new tests (e.g., test_source_filter_glob_wildcards,
test_source_filter_special_chars, test_source_filter_windows_backslashes,
test_source_filter_invalid_pattern_error) that use setup_project to create files
and assert behavior for glob patterns like "*.cpp", "**", "?", patterns
containing regex-special chars (e.g., ".", "+"), Windows-style backslash inputs,
and malformed patterns (e.g., "+<>", "invalid") to ensure correct matching and
error handling; keep tests concise, call SourceScanner::new(&src_dir,
&build_dir) and verify returned Ok results and Err for invalid patterns.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@crates/fbuild-build/src/pipeline.rs`:
- Around line 235-253: The cleanup logic in is_platformio_debug_cleanup_flag
misses the bare "-ggdb" (5 chars) case; update is_platformio_debug_cleanup_flag
(and only that function) to treat "-ggdb" as a cleanup flag in addition to
"-ggdb[0-3]" — e.g. accept either a 5-char exact "-ggdb" or a 6-char "-ggdbN"
where N ∈ {0,1,2,3}; leave is_platformio_debug_link_flag as-is so it continues
to match "-g" and "-ggdb" during linking.

In `@crates/fbuild-build/src/source_scanner.rs`:
- Around line 61-71: Add doc comments to SourceFilter and SourceFilterRule
describing their PlatformIO-style matching semantics: explain that
SourceFilter.rules is a list of SourceFilterRule entries, each rule's include
boolean indicates whether matching paths are allowed (include=true) or denied
(include=false), and matcher (Regex) is used to test paths; clarify that
SourceFilter.has_include_rules toggles the default for unmatched files — if any
include rules exist unmatched files are excluded, otherwise unmatched files are
included by default. Place these comments above the struct definitions for
SourceFilter and SourceFilterRule to make the behavior explicit to future
readers.
- Around line 781-812: Add unit tests expanding coverage for
SourceScanner::scan_sketch_sources_filtered: create new tests (e.g.,
test_source_filter_glob_wildcards, test_source_filter_special_chars,
test_source_filter_windows_backslashes,
test_source_filter_invalid_pattern_error) that use setup_project to create files
and assert behavior for glob patterns like "*.cpp", "**", "?", patterns
containing regex-special chars (e.g., ".", "+"), Windows-style backslash inputs,
and malformed patterns (e.g., "+<>", "invalid") to ensure correct matching and
error handling; keep tests concise, call SourceScanner::new(&src_dir,
&build_dir) and verify returned Ok results and Err for invalid patterns.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 1c292d00-4482-4ded-beb0-497f75c2abce

📥 Commits

Reviewing files that changed from the base of the PR and between d2cd43a and 8086d1f.

📒 Files selected for processing (17)
  • crates/fbuild-build/src/apollo3/orchestrator.rs
  • crates/fbuild-build/src/avr/orchestrator.rs
  • crates/fbuild-build/src/ch32v/orchestrator.rs
  • crates/fbuild-build/src/esp32/orchestrator.rs
  • crates/fbuild-build/src/esp8266/orchestrator.rs
  • crates/fbuild-build/src/nrf52/orchestrator.rs
  • crates/fbuild-build/src/pipeline.rs
  • crates/fbuild-build/src/renesas/orchestrator.rs
  • crates/fbuild-build/src/rp2040/orchestrator.rs
  • crates/fbuild-build/src/sam/orchestrator.rs
  • crates/fbuild-build/src/script_runtime.rs
  • crates/fbuild-build/src/script_runtime_harness.py
  • crates/fbuild-build/src/silabs/orchestrator.rs
  • crates/fbuild-build/src/source_scanner.rs
  • crates/fbuild-build/src/stm32/orchestrator.rs
  • crates/fbuild-build/src/teensy/orchestrator.rs
  • crates/fbuild-config/src/ini_parser.rs

@zackees zackees merged commit 2549b09 into main Apr 14, 2026
76 of 78 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Real-world platformio.ini sample reveals remaining native compatibility gaps

1 participant