Skip to content

ruby-rbs-sys: support wasm32 targets#2992

Open
rubys wants to merge 1 commit into
ruby:masterfrom
rubys:rust-wasm-bindings
Open

ruby-rbs-sys: support wasm32 targets#2992
rubys wants to merge 1 commit into
ruby:masterfrom
rubys:rust-wasm-bindings

Conversation

@rubys

@rubys rubys commented Jun 14, 2026

Copy link
Copy Markdown

What

Teach ruby-rbs-sys's build script to support wasm32-* targets:

  • Compile the vendored RBS C parser with the WASI SDK's clang (via WASI_SDK_PATH).
  • Generate the FFI bindings against the host target (--target=$HOST, layout_tests(false)) rather than the wasm target.

This mirrors ruby-prism-sys's existing wasm build support.

Why

Running bindgen against the wasm target is libclang-version-fragile. Across libclangs I see two distinct failures, both on wasm32-wasip1:

  • some libclangs drop all rbs_* function declarations;
  • others emit the forward-referenced node structs (rbs_namespace, rbs_type_name, rbs_ast_symbol, rbs_types_block, rbs_ast_declarations_class_super) as opaque, so the generated layout assertions overflow (E0080).

The generated #[repr(C)] declarations are layout-portable, so generating them for the host and compiling them for wasm32 is both correct and reliable. The C parser is still compiled for wasm by the WASI SDK clang.

Testing

  • cargo build -p ruby-rbs-sys --target wasm32-wasip1 and cargo build -p ruby-rbs --target wasm32-wasip1 both succeed.
  • Runtime: a cdylib calling rbs_parser_newrbs_parse_signature → walking signature.declarations (and the high-level ruby_rbs::node::parse) runs correctly under a WASI runtime.
  • Native builds are unchanged — the wasm-specific configuration is gated on the target.

🤖 Generated with Claude Code

Compile the vendored RBS C parser to wasm with the WASI SDK's clang
(via WASI_SDK_PATH), and generate the FFI bindings against the host
target (--target=$HOST, layout_tests off) rather than the wasm target.

Running bindgen against the wasm target is libclang-version-fragile:
some libclangs drop all function declarations, others emit the
forward-referenced node structs (rbs_namespace, rbs_type_name,
rbs_ast_symbol, ...) as opaque, which breaks the generated layout
assertions. The emitted #[repr(C)] declarations are layout-portable,
so generating them for the host and compiling them for wasm32 is both
correct and reliable. Mirrors ruby-prism-sys's wasm build support.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@rubys rubys force-pushed the rust-wasm-bindings branch from bf7872d to 5bf71cb Compare June 14, 2026 22:19
rubys added a commit to rubys/roundhouse that referenced this pull request Jun 14, 2026
…er spike

Drop the rubys/rbs-rust fork: roundhouse now depends on the published ruby-rbs = "0.3" on every target. wasm only needs ruby-rbs-sys built for wasm32 — its vendored RBS C parser compiled by the WASI-SDK clang, and its bindgen run against the host target (#[repr(C)] is layout-portable), sidestepping the libclang-version-fragile bindgen-against-wasm failures.

That build.rs support is upstreamed as ruby/rbs#2992; until it publishes, wasm/Cargo.toml carries a temporary [patch.crates-io] ruby-rbs-sys local path (repin once merged). Build requires WASI_SDK_PATH=/opt/wasi-sdk.

Also lands the rung-A Phase 0 browser spike (wasm/browser-spike/): a shared wasi-shim.mjs + transpile.mjs driving both the Node validator and a static browser page — proving the compiler transpiles real-blog in a real tab with no WebContainer/npm/bundler. Plus docs/browser-demo-plan.md.

Verified: native cargo check --lib clean; wasm build clean (3.2 MB); node round-trip OK.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
rubys added a commit to rubys/roundhouse that referenced this pull request Jun 14, 2026
Make wasm/playground/ self-contained so it deploys as a static dir: vendor the C-ABI driver (transpile.mjs + wasi-shim.mjs) and check in the prebuilt compiler roundhouse_wasm.wasm (3.2 MB) + a seed fixture.json; playground.js now imports/fetches from ./ instead of ../browser-spike/.

Add a build-site CI step that bundles _site/playground/ (copies the dir, regenerates fixture.json from the freshly-built real-blog so the editor's seed app tracks create-blog), mirroring how /blog/ is assembled. Link it from the landing page and the demo page.

The compiler wasm is checked in, NOT built in CI: a runner build needs the WASI SDK + a published ruby-rbs-sys (upstream-pending as ruby/rbs#2992). Rather than block on that, the binary is committed and refreshed by hand on compiler/emit changes (see wasm/playground/README.md). Switch to a CI build + drop the binary once #2992 lands. Documented in docs/browser-demo-plan.md (new 'Publishing to Pages' section).

Verified: self-contained playground and the CI-assembled bundle both pass verify-playground.mjs (Playwright); ci.yml is valid YAML.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
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