Repository navigation
fix(gui): select the GUI bridge by backend name, not the enum (#386) - #414
Conversation
An external `.backend_package` leaves `cfg.backend` at its `.raylib` enum default (the tag is meaningless for a named package). `getBridgeForBackend` keyed off that enum, so an out-of-tree bgfx game pulled the RAYLIB imgui bridge (rlImGui) — dragging in an old, Zig-0.16-incompatible raylib-zig and failing the build. Same class of bug as the preview-readback gate (#386 Phase 6b). Select the bridge by `cfg.backendName()` over the same named `Bridges` fields: an external "bgfx" resolves to `bridges.bgfx`, and built-ins are byte-identical (their name IS the enum tag). A name with no declared bridge (null backend, or a third-party backend the GUI plugin doesn't bridge) returns null → the caller's existing "no bridge for backend X" diagnostic. Surfaced by validating Flying Platform (bgfx + imgui + zig_ecs + plugins) against the extracted out-of-tree labelle-bgfx package: before this, FP staged the rlImGui bridge and failed to compile; after, it stages bgfx_imgui_bridge and the full desktop game builds (BUILD_RC=0, 37 MB binary linking labelle-bgfx).
There was a problem hiding this comment.
Code Review
This pull request replaces the enum-based backend bridge selection with a name-based selection (getBridgeForBackendName) to correctly resolve external backends, and adds a corresponding regression test. The reviewer suggests improving getBridgeForBackendName by using Zig's compile-time reflection (std.meta.fields) to dynamically iterate over the fields of the Bridges struct instead of hardcoding string comparisons.
Important
The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.
| fn getBridgeForBackendName(bridges: Bridges, name: []const u8) ?BridgeDef { | ||
| if (std.mem.eql(u8, name, "raylib")) return bridges.raylib; | ||
| if (std.mem.eql(u8, name, "sokol")) return bridges.sokol; | ||
| if (std.mem.eql(u8, name, "sdl")) return bridges.sdl; | ||
| if (std.mem.eql(u8, name, "bgfx")) return bridges.bgfx; | ||
| if (std.mem.eql(u8, name, "wgpu")) return bridges.wgpu; | ||
| return null; | ||
| } |
There was a problem hiding this comment.
Instead of manually hardcoding string comparisons for each backend, we can use Zig's compile-time reflection (std.meta.fields) to iterate over the fields of the Bridges struct. This ensures that if any new backends are added to the Bridges struct in the future, this function will automatically support them without requiring manual updates.
fn getBridgeForBackendName(bridges: Bridges, name: []const u8) ?BridgeDef {
inline for (std.meta.fields(Bridges)) |field| {
if (std.mem.eql(u8, name, field.name)) {
return @field(bridges, field.name);
}
}
return null;
}
There was a problem hiding this comment.
Done — switched to an inline for over @typeInfo(Bridges).@"struct".fields matching field name == backend name. Same behavior, and a new bridge field now needs no change here. Thanks.
…ini) Replace the hardcoded per-backend string comparisons with an inline-for over the Bridges struct fields — same behavior, but adding a bridge field no longer needs a matching line here. (gemini review on #414.)
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Repository UI Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (1)
📝 WalkthroughWalkthroughIn Bridge name-based selection
Estimated code review effort🎯 2 (Simple) | ⏱️ ~10 minutes Possibly related PRs
Poem
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Comment |
… (#418) Pluggable-backends Phases 5+6 (epic #386): the assembler can now FETCH, verify, and build out-of-tree backend packages, and bgfx is extracted to its own repo. - #409 6a: remote .backend_package cache-fetch (fetched like a plugin) - #410 6b: contract-verify an external backend (assertBackend/Window/Input) - #411: conform raylib + null windows to the canonical window contract - #412 Phase 5: enum-as-shorthand resolution (a built-in tag can resolve to a package) - #413 6c: bgfx extracted -> github.com/labelle-toolkit/labelle-bgfx; opt-in CI-verified - #414: select the GUI bridge by backend name, not the enum (external backends) - #415: labelle-bgfx v0.2.0 — gamepad sources extracted to their own packages - #416/#417: the two flip-blockers (callback-external guard; android enum-fallthrough) Opt-in today via .backend_package; built-in .backend = .bgfx still ships bundled (the default-flip is a follow-up gated on this release). Built-in backends are byte-identical. External bgfx validated on-device (Galaxy Tab A7): builds, runs crash-free, behaves identically to bundled.
External backends pulled the wrong GUI bridge
Found by validating Flying Platform (bgfx + imgui) against the extracted out-of-tree
labelle-bgfxpackage — the first real-game test of the extraction.getBridgeForBackendselected the imgui bridge variant from the closedconfig.Backendenum. An external.backend_packageleavescfg.backendat its.raylibenum default (the tag is meaningless for a named package), so an out-of-tree bgfx game resolved the raylib (rlImGui) bridge — dragging in an old, Zig-0.16-incompatible raylib-zig (std.mem.trimLeft/std.process.getEnvVarOwnedremoved) and failing the build. Same class of bug as the preview-readback gate fixed in Phase 6b.Fix
Select by
cfg.backendName()over the same namedBridgesfields:"bgfx"→bridges.bgfx✓null→ the caller's existing "no bridge for backend X" diagnosticVerification
backend_packagestagedrlimgui_bridge(raylib-zig 5.6.0-dev), bundled.backend = .bgfxstagedbgfx_imgui_bridge. After the fix, external bgfx stagesbgfx_imgui_bridge(0 raylib refs).labelle-bgfx—BUILD_RC=0, 37 MB binary linking the external package.getBridgeForBackendName);zig build testgreen.Summary by CodeRabbit