Skip to content

feat(#461): manifest-v2 PR10 — bgfx all platforms (last backend converted) - #471

Merged
apotema merged 1 commit into
mainfrom
feat/453-manifest-v2-pr10-bgfx
Jul 1, 2026
Merged

apotema merged 1 commit into
mainfrom
feat/453-manifest-v2-pr10-bgfx

Conversation

@apotema

@apotema apotema commented Jul 1, 2026 •

Copy link
Copy Markdown
Contributor

PR 10 of the manifest-v2 epic (#461, #453 item 3). Converts bgfx — the last and hardest backend — across desktop + android from a single manifest. With this, all 6 backends are v2-modeled.

bgfx v2 fixture (backends/bgfx_v2/backend.manifest.v2.zon)

Faithful translation of the real labelle-bgfx v1 + enum sections. id="labelle.bgfx", capabilities {android, surface_loss, compressed_textures, screenshots, gamepad_polling, raw_gui_adapter}.

  • desktop: loop_style=.loop, artifacts bgfx+glfw, base dep_options gui_enabled + desktop-only gamepad_enabled/gamepad_hidapi, hookless.
  • android: loop_style=.callback, target=.resolved, package=.apk, pic, link_libc, artifact bgfx, the android_app extra module with root_alias="backend_app", system_libs.android={android,log,EGL,GLESv3,m,dl,mediandk,aaudio}, build_hook.

bgfx hook (backends/bgfx_v2/backend.hook.zig)

Std-only. Android resolve_target (ABI) + post_wire (bgfx-Android NDK residual: addLibraryPath + libc.txt). Unlike sokol, no addSystemIncludePath on the artifact (bgfx/bx/bimg C++ are NDK-wired by the backend's own build.zig). ctx.android_target_sdk required (no orelse 34). Compiled as a test target.

Emitter extension (the only new codegen)

renderAndroidBackendDepV2 now declares extra_modules under their root_alias (const backend_app = backend_dep.module("android_app");) + walks them with unifyCoreDiamond. Per-platform loop_style was already schema-supported (raylib desktop .loop/wasm .callback proved it) — bgfx just adds android .callback.

Goldens + the load-bearing alias

  • bgfx_v2_desktop.build.zig — hookless, generic walk, bgfx+glfw on both exe and test_root.
  • bgfx_v2_android.build.zig — imports the hook, resolve_target+post_wire, const backend_app = backend_dep.module("android_app") published as .{ .name = "backend_app", .module = backend_app } (asserted; backend_android_app never appears), generic diamond over backend_app+backend_input, declarative NDK syslibs, apk via the packager.
  • A dedicated test proves the android_app→backend_app alias (§3 review finding — wrong alias breaks the NativeActivity shell import).

Core-diamond coverage

Desktop sdl_gamepad + android android_gamepad are transitive sub-packages of backend_input; the generic unifyCoreDiamond walk recurses into them (no per-backend override site). Android also covers backend_input's direct labelle-core (#310) + the backend_app shell.

sokol desktop byte anchor + ALL prior goldens (sokol android/ios/wasm, null, wgpu, raylib, sdl) unchanged; v1/enum unchanged (v2 opt-in). zig build test + zig build exit 0.

Ref #461, #453.

https://claude.ai/code/session_017pW3ifKf9wgxNg4viy6okw

Summary by CodeRabbit

  • New Features

    • Added bgfx v2 support for Android and desktop builds.
    • Android builds now handle device/emulator target selection and package/sign APKs automatically.
    • Desktop builds now include bgfx and GLFW wiring in generated build output.
  • Bug Fixes

    • Improved Android SDK/NDK detection and validation to reduce build-time failures.
    • Added clearer handling when required Android target settings are missing.
  • Tests

    • Added new golden and unit test coverage for bgfx v2 build generation on both desktop and Android.

Convert bgfx, the last and hardest backend, to the manifest-v2 build graph
(epic #453 item 3, PR 10, design §8). bgfx is the first backend needing BOTH
per-platform loop_style (desktop .loop, android .callback) AND a platform-only
extra_modules with a non-default root_alias (android's android_app → backend_app),
both derived from ONE manifest.

- backends/bgfx_v2/backend.manifest.v2.zon: faithful v2 translation of the real
  labelle-bgfx v1 manifest + enum backend_bgfx/link_bgfx/backend_bgfx_android/
  android_link_bgfx sections. Desktop: .loop, .native, bgfx+glfw artifacts, base
  gui_enabled + desktop gamepad_* dep_options. Android: .callback, .resolved,
  .apk, pic, link_libc, bgfx artifact, android_app extra module aliased to
  backend_app, NDK system libs, build_hook.
- backends/bgfx_v2/backend.hook.zig: std-only android resolve_target (ABI) +
  post_wire (bgfx-Android NDK residual: addLibraryPath + libc.txt; no artifact
  addSystemIncludePath since bgfx C++ TUs are backend-wired). android_target_sdk
  required (panics on null). Compiled as a test target in build.zig.
- manifest_v2_splice: extend the android backend-dep emitter to declare + walk
  PlatformEntry.extra_modules under their root_alias (the backend_app alias — the
  load-bearing correctness bit, design §3 review-correction #3).
- Golden cells: test/goldens/bgfx_v2_{desktop,android}.build.zig + assertions
  (AST-valid; desktop hookless + bgfx/glfw on exe AND test_root; android hook
  phases + backend_app alias + generic unifyCoreDiamond + apk packaging).

Per-platform loop_style is already schema-supported (PlatformEntry); the emitter
extension needed was extra_modules root_alias. sokol desktop byte anchor + all
prior goldens unchanged; v1/enum path unchanged (v2 is opt-in). zig build test
exit 0.

Claude-Session: https://claude.ai/code/session_017pW3ifKf9wgxNg4viy6okw
@coderabbitai

coderabbitai Bot commented Jul 1, 2026 •

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 479bc7fb-9258-47f8-9545-d7eb8fe3f9f3

📥 Commits

Reviewing files that changed from the base of the PR and between c19dd89 and c751de0.

📒 Files selected for processing (8)
  • backends/bgfx_v2/backend.hook.zig
  • backends/bgfx_v2/backend.manifest.v2.zon
  • build.zig
  • src/codegen/manifest_v2_splice.zig
  • test/build_zig_tests.zig
  • test/goldens/bgfx_v2_android.build.zig
  • test/goldens/bgfx_v2_desktop.build.zig
  • test/helpers.zig

📝 Walkthrough

Walkthrough

Adds a bgfx v2 backend manifest and an Android-focused build hook module (target resolution, NDK sysroot detection, libc.txt generation), extends manifest_v2_splice codegen to wire Android extra modules and unifyCoreDiamond, adds a bgfx_hook_tests build target, and adds desktop/android golden build.zig fixtures with corresponding tests and helpers.

Changes

bgfx v2 manifest, hook, and codegen

Layer / File(s) Summary
bgfx v2 manifest definition
backends/bgfx_v2/backend.manifest.v2.zon
Declares manifest metadata, capabilities, base modules/dependency options, Android system libraries, desktop/android platform build configs, and the backend.hook.zig hook reference.
Android build hook implementation
backends/bgfx_v2/backend.hook.zig
Implements hook ABI/platform/error types, resolve_target for Android arch selection, post_wire for NDK sysroot detection and android-libc.txt generation, plus unit tests.
build.zig test target wiring
build.zig
Adds bgfx_hook_tests compiling/running the hook file as a typecheck+test gate wired into test_step.
manifest_v2_splice codegen for Android extra modules
src/codegen/manifest_v2_splice.zig
Emits module declarations for Android extra_modules under root_alias and includes them in the generated unifyCoreDiamond walk.
Desktop and Android golden build.zig fixtures
test/goldens/bgfx_v2_desktop.build.zig, test/goldens/bgfx_v2_android.build.zig
Adds golden build scripts wiring core/gfx/engine/bgfx modules, overrideImport/unifyGfxSubpackageCore/unifyCoreDiamond helpers, artifact linking, and Android APK packaging/signing.
Golden tests and fixture helpers
test/build_zig_tests.zig, test/helpers.zig
Adds desktop/android golden test cells validating generated output and wiring, plus a bgfx_v2_fixture_package/genBgfxV2BuildZig test helper.

Estimated code review effort: 4 (Complex) | ~60 minutes

Sequence Diagram(s)

sequenceDiagram
  participant Build as std.Build
  participant Hook as backend.hook.zig
  participant NDK as Android NDK/SDK

  Build->>Hook: resolve_target(ctx)
  Hook->>Hook: selectAndroidArch(host_arch, emulator, arch_opt)
  Hook-->>Build: ResolvedTargetInfo

  Build->>Hook: post_wire(ctx)
  Hook->>Hook: requireAndroidSdk(ctx)
  Hook->>NDK: detect NDK sysroot (ANDROID_NDK_HOME/ANDROID_HOME)
  Hook->>Hook: libcTxt(include_dir, sys_include_dir, crt_dir)
  Hook-->>Build: attach android-libc.txt to root .so artifact
Loading

Possibly related issues

Possibly related PRs

Poem

A rabbit hops through NDK trees,
Sniffing sysroots on the breeze,
Two hooks it weaves, resolve then wire,
Signing APKs beside the fire,
Bgfx builds both desk and phone —
Thump thump, this warren's fully grown! 🐇📦

🚥 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 title clearly matches the main change: converting bgfx to manifest-v2 across desktop and Android.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/453-manifest-v2-pr10-bgfx

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

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Code Review

This pull request implements the manifest-v2 migration for the bgfx backend, introducing a dedicated build hook (backend.hook.zig) and a v2 manifest (backend.manifest.v2.zon) to handle both desktop and android platforms. It also updates the codegen splice logic to support platform-only extra modules and adds corresponding golden tests. Feedback on the changes includes correcting the usage of std.ArrayList to std.ArrayListUnmanaged in the NDK detection logic, and preferring standard logging (std.log.err) over std.debug.print for user-facing errors.

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.

const ndk_dir = b.pathJoin(&.{ home, "ndk" });
var dir = std.Io.Dir.cwd().openDir(io, ndk_dir, .{ .iterate = true }) catch return null;
defer dir.close(io);
var candidates: std.ArrayList(NdkCandidate) = .empty;

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

high

The std.ArrayList type is a managed array list that stores its allocator internally and does not support .empty initialization. Its deinit and append methods do not accept an allocator argument. Since you are initializing it with .empty and passing b.allocator to deinit and append, you should use std.ArrayListUnmanaged instead.

        var candidates: std.ArrayListUnmanaged(NdkCandidate) = .empty;
References
  1. In Zig 0.16, the deinit API for an unmanaged ArrayList requires passing the allocator.

const emulator_mode = b.option(bool, "emulator", "Build for Android emulator (x86_64 on Intel Mac, arm64 on Apple Silicon)") orelse false;
const android_arch_opt = b.option([]const u8, "android_arch", "Android target arch (arm64|x86_64). Overrides -Demulator when set.");
const android_arch = selectAndroidArch(b.graph.host.result.cpu.arch, emulator_mode, android_arch_opt) catch {
std.debug.print("build.zig: unknown -Dandroid_arch value (expected arm64 or x86_64)\n", .{});

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

medium

In CLI tools (including build scripts and hooks), standard logging facilities like std.log.err should be preferred over debug-specific print functions like std.debug.print for user-facing warnings and errors. Note that std.log functions automatically append a newline, so the trailing \n should be omitted.

                std.log.err("build.zig: unknown -Dandroid_arch value (expected arm64 or x86_64)", .{});
References
  1. In CLI tools, use standard logging facilities (e.g., std.log.warn) or write to stderr for user-facing warnings, rather than using debug-specific print functions (e.g., std.debug.print).

@apotema

apotema commented Jul 1, 2026

Copy link
Copy Markdown
Contributor Author

Both gemini findings evaluated and declined (with reasons):

  1. HIGH — std.ArrayList .empty (hook.zig:237): false positive. Zig 0.16's std.ArrayList is the unmanaged variant — var x: std.ArrayList(T) = .empty; with deinit(allocator)/items is the correct 0.16 idiom. It compiles (CI green) and is identical to the already-merged, reviewed sokol hook (backends/sokol/backend.hook.zig:313). The finding applies pre-0.16 managed-ArrayList API knowledge.
  2. MEDIUM — std.debug.print vs std.log (hook.zig:132): the merged sokol hook uses the identical std.debug.print + @panic for the same -Dandroid_arch error path (sokol hook:225). Changing only bgfx would make the two hooks inconsistent; the build-hook-error convention is already established. Not changing.

CodeRabbit found no issues. Merging.

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.

1 participant