Skip to content

Key wasi-sysroot build flags on the toolchain instead of the target triple - #666

Open
graial wants to merge 2 commits into
ruby:mainfrom
graial:adjust_predicate_for_other_wasisdk_hosts
Open

Key wasi-sysroot build flags on the toolchain instead of the target triple#666
graial wants to merge 2 commits into
ruby:mainfrom
graial:adjust_predicate_for_other_wasisdk_hosts

Conversation

@graial

@graial graial commented Sep 3, 2026

Copy link
Copy Markdown

Summary

Note: This bug report and fix is AI-assisted

Several build products decide whether to pass wasi-libc's emulation flags by testing the target triple string against wasm32-unknown-wasi. Those flags exist because the code is being compiled against wasi-sysroot, a property of the toolchain, not the target.

This means that a target using RubyWasm::WASISDK with triple other than wasm32-unknown-wasi* is configured with the wasi-sdk compiler but fails to build without the flags, with an unhelpful failure message.

This PR adds a wasi_sysroot? predicate to RubyWasm::Toolchain, returning false by default and true on WASISDK, and switches the sysroot-driven sites to test it.

The bug

lib/ruby_wasm/build/product/openssl.rb:45

if @target.triple.start_with?("wasm32-unknown-wasi") 

A wasi-sdk target failing this test gets none of -D_WASI_EMULATED_SIGNAL, -D_WASI_EMULATED_PROCESS_CLOCKS, -D_WASI_EMULATED_MMAN, -D_WASI_EMULATED_GETPID, -DNO_CHMOD or -DHAVE_FORK=0. OpenSSL then fails on wasi-libc's signal.h:

error: "wasm lacks signal support; to enable minimal signal emulation, compile with -D_WASI_EMULATED_SIGNAL and link with -lwasi-emulated-signal"

lib/ruby_wasm/build/product/crossruby.rb:349 has the same gate, carrying WASMOPT, WASI_SDK_PATH, ac_cv_func_fchmod=no, ac_cv_func_chmod=no and ac_cv_func_realpath=no. CRuby's own configure hits the equivalent wall immediately after OpenSSL is cleared.

The base array in openssl.rb already carries -no-sock, -no-dgram, -no-threads and -Wl,--allow-undefined unconditionally, so a failing build looks partly wasm-aware. That makes this harder to spot than it should be — the build appears to know it is targeting wasm, and fails anyway.

Changes

  1. Toolchain#wasi_sysroot? returning false; WASISDK#wasi_sysroot? returning true. Subclasses of WASISDK inherit the correct answer.
  2. openssl.rb and crossruby.rb test the predicate instead of the triple prefix. In crossruby.rb the sysroot block is hoisted out of the case, leaving the case for genuinely target-specific concerns. Its else arm still raises on an unknown target, but now defers to the predicate rather than to a triple prefix, so a wasi-sdk target is not rejected by the guard after the block above has already handled it.
  3. RBS signatures for both predicate definitions.
  4. Unit tests asserting the predicate on Toolchain, WASISDK and Emscripten.

Sites deliberately not changed

  • toolchain.rb:29 dispatches triple to toolchain and cannot be predicate driven without circularity.
  • packager.rb:47 gates the wasip1 component adapter, which is genuinely specific to that triple.
  • packager.rb:100, cli.rb:52 are defaults.
  • wasi_vfs.rb:15 is a hardcoded build target for the wasi-vfs crate.

The test applied at each site: is this here because of the sysroot, or because of the target's identity? Only the former became the predicate.

Naming

wasi_sysroot? names the actual reason the flags exist. wasi? was avoided deliberately: that ambiguity is what caused the bug, since a target can compile against wasi-sysroot without being wasip1.

Testing

Built 3.3-wasm32-unknown-wasip1-full on upstream/main and on this branch. Both artifacts are byte-identical:

Artifact upstream/main This branch
ruby 49135b1095a5a61cea452e4f2e34d42efcd3f5831fca4a4e04f205a458db7720 49135b1095a5a61cea452e4f2e34d42efcd3f5831fca4a4e04f205a458db7720
libruby-static.a 7a79f61e8c03edba48cbde3586a1668eeb7f814146825798b952bd633ff1db15 7a79f61e8c03edba48cbde3586a1668eeb7f814146825798b952bd633ff1db15

full rather than minimal because build.rb:53 constructs OpenSSLProduct unconditionally, so full exercises the OpenSSL gate that minimal may not reach.

That result is what the change predicts, because the predicate returns the same answer as the triple test for every target that exists today:

  • wasip1 — triple starts wasm32-unknown-wasi, so the old gate is true; WASISDK#wasi_sysroot? is true. No change.
  • emscripten — old gate false; Emscripten descends from Toolchain, not WASISDK, so the predicate is false. No change.

Both cases are covered by unit tests on the predicate itself. The emscripten case is asserted by test but not by a build — worth flagging rather than leaving for someone to notice.

steep check is clean.

Provenance

Found while adding a wasi-sdk target for the Internet Computer (#653). The bug is not specific to that target: it bites any new WASISDK subclass whose triple is not named wasm32-unknown-wasi*, and it is worth fixing whether or not ruby.wasm decides to support an ICP target.

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