Skip to content

web: Fix MVP wasm build by explicitly disabling post-MVP features#23756

Merged
torokati44 merged 1 commit into
ruffle-rs:masterfrom
SuchAFuriousDeath:fix-mvp-build
May 20, 2026
Merged

web: Fix MVP wasm build by explicitly disabling post-MVP features#23756
torokati44 merged 1 commit into
ruffle-rs:masterfrom
SuchAFuriousDeath:fix-mvp-build

Conversation

@SuchAFuriousDeath
Copy link
Copy Markdown
Collaborator

@SuchAFuriousDeath SuchAFuriousDeath commented May 19, 2026

Description

Fixes #23751

-C target-cpu=mvp alone no longer keeps the produced wasm strictly
MVP. Two separate paths leak post-MVP target features back in:

  1. Rust 1.82+ enables reference-types and multivalue by default
    for wasm32-unknown-unknown; target-cpu=mvp does not unset them.
  2. C dependencies compiled by cc-rs/clang (e.g. jpegxr's jxrlib)
    produce object files whose target_features section carries
    +reference-types/+multivalue regardless of the Rust flags.

Either path leaves +reference-types in the final module's
target_features. wasm-bindgen 0.2.94+ then auto-enables externref
transforms and fails with failed to find the __wbindgen_externref_table_dealloc function, because the
build-std'd MVP code lacks the runtime helper.

Explicitly pass -C target-feature=-reference-types,-multivalue
to rustc and -mno-reference-types -mno-multivalue to clang via
CFLAGS_wasm32_unknown_unknown for the MVP profile only.

Testing

Prereqs:

  • Rust 1.82+
  • rustup component add rust-src (for -Z build-std)
  • wasm-bindgen-cli 0.2.120 matching lockfile (cargo install wasm-bindgen-cli --version 0.2.120)
  • Node + clang/LLVM for jpegxr's bindgen

Reproduce the bug on master:
cd web
npm ci
CARGO_FEATURES=jpegxr BUILD_WASM_MVP=true npm run build

expect: error: failed to find the __wbindgen_externref_table_dealloc function

Checklist

  • I, a human, have self-reviewed this PR and fully understand the changes within.
  • I have made or updated tests where possible.
  • All of my commits are properly scoped, compile successfully, and pass all tests.
  • This PR does not make sense to split up into smaller PRs.
  • An LLM was involved in the authoring of this code.

@SuchAFuriousDeath SuchAFuriousDeath force-pushed the fix-mvp-build branch 3 times, most recently from 871e034 to 1af82d7 Compare May 19, 2026 16:33
@danielhjacobs
Copy link
Copy Markdown
Contributor

danielhjacobs commented May 19, 2026

Didn't we deal with the Rust 1.82+ issue in #18528 by building std, which we do "stably" by setting RUSTC_BOOTSTRAP to 1 to use Nightly features with stable Rust when building the vanilla module. Any CI scripts that use either of those commands (Nightly release, Dockerfile, dockerfile test) also need to install the rust-src component.

Comment thread web/packages/core/tools/build_wasm.ts Outdated
@danielhjacobs
Copy link
Copy Markdown
Contributor

Here the mvp “cpu” is a placeholder in LLVM for disabling all supported features by default. Cargo’s -Zbuild-std feature, a Nightly Rust feature, is then used to recompile the standard library in addition to your own code. This will produce a binary that uses only the original WebAssembly features by default and no proposals since its inception.

https://doc.rust-lang.org/beta/rustc/platform-support/wasm32-unknown-unknown.html#enabled-webassembly-features

@danielhjacobs
Copy link
Copy Markdown
Contributor

Mainly I would have expected https://ruffle.rs/demo/ to have stopped working on Pale Moon if this were really an issue, as https://repo.palemoon.org/MoonchildProductions/UXP/issues/2647 is still an issue

@torokati44
Copy link
Copy Markdown
Member

My guess is that the problem comes mainly from newer clang enabling those extensions, so the CFLAGS part of the fix might suffice.

@SuchAFuriousDeath
Copy link
Copy Markdown
Collaborator Author

I got tangled up in this a little bit, the PR is adjusted. Here is where we stand:

The existing -Ctarget-cpu=mvp + -Zbuild-std + RUSTC_BOOTSTRAP=1 setup from #18528 does produce a strictly-MVP Rust side on current rustc (1.95 here). I confirmed that by ablation: the Rust-side fix I'd originally pushed turned out to be redundant. I've simplified the PR — it's now a one-knob change: set CFLAGS_wasm32_unknown_unknown=-mno-reference-types -mno-multivalue for the MVP build path. No rustflags change.

So the rustc-docs quote you linked is literally correct, and the existing system works for everything compiled by rustc. The breakage is purely a cc-rs/clang leak that the existing system does not (and cannot) control:

  1. jpegxr pulls in Microsoft's jxrlib (C) via cc-rs.
  2. cc-rs invokes clang for wasm32-unknown-unknown with clang's defaults, which since LLVM 16-ish include +reference-types and +multivalue. Those land in the C object files' target_features custom sections.
  3. wasm-ld merges target_features into the final module. I dumped the failing wasm from master: it has +reference-types and +multivalue even with -Ctarget-cpu=mvp + -Zbuild-std — entirely contributed by the C objects.
  4. wasm-bindgen 0.2.94+ auto-enables externref transforms when it sees +reference-types in target_features. The Rust-side code was built without externref support, so __wbindgen_externref_table_dealloc isn't present → failed to find the __wbindgen_externref_table_dealloc function.

Tracked upstream as wasm-bindgen/wasm-bindgen#4654 (still open). Setting CFLAGS_wasm32_unknown_unknown=-mno-reference-types -mno-multivalue is the exact workaround recommended in that issue's discussion — it makes cc-rs/clang produce strict MVP objects, so the linked module's target_features stays clean.

Re: ruffle.rs/demo on Pale Moon — that demo's default web build does not enable jpegxr (or any feature that pulls in C deps via cc-rs). No C objects means no clang leak, so the strict-MVP guarantee from rustc holds end-to-end and Pale Moon is happy. The breakage only surfaces with CARGO_FEATURES=jpegxr (the env in the original bug report). Repro:

cd web && CARGO_FEATURES=jpegxr BUILD_WASM_MVP=true npm run build

Master fails with the externref error. Drop jpegxr and master passes. This PR makes both pass.

@torokati44
Copy link
Copy Markdown
Member

+1 reason to sometime rewrite the jpegxr loader to Rust. And get rid of the intermediate TIFF format with it. And the disgusting fakelibc too.
(I heard AI can now port an entire server-side JS runtime from Zig to Rust in a week with no regressions! 👀😏 And we even have c2rust to boot!)

Comment thread web/packages/core/tools/build_wasm.ts
Copy link
Copy Markdown
Member

@torokati44 torokati44 left a comment

Choose a reason for hiding this comment

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

The comment is a bit verbose - but if anyone, I don't mind that one bit! :P
JS nitpicks notwithstanding, I agree that this is a good fix for the cause of the linked issue, and I also don't know a better way to pass the flag in, but in an envvar. Any potentially preset value there is nicely appended to as well. Thanks for figuring this out!

When the `jpegxr` feature is enabled, Microsoft's jxrlib (C) is
compiled by cc-rs via clang. Clang's default `wasm32-unknown-unknown`
target enables `reference-types` and `multivalue`, and those bits
land in the produced .o files' `target_features` custom section. The
linker merges those sections into the final wasm module, so even
though the Rust side is built strictly MVP (`-Ctarget-cpu=mvp`
plus rebuilt std via `-Zbuild-std`), the final module advertises
`+reference-types` in `target_features`.

wasm-bindgen 0.2.94+ then auto-enables externref transforms when it
sees that bit and fails with `failed to find the
__wbindgen_externref_table_dealloc function`, because the MVP-built
Rust code does not contain that runtime symbol.

Force clang into strict MVP via
`CFLAGS_wasm32_unknown_unknown=-mno-reference-types -mno-multivalue`
for the MVP build path. The Rust side already produces clean MVP
metadata on current rustc, so no rustflags change is needed.

Fixes ruffle-rs#23751. Upstream tracking: wasm-bindgen/wasm-bindgen#4654.
@torokati44 torokati44 enabled auto-merge (rebase) May 20, 2026 12:14
@torokati44 torokati44 added A-build Area: Build scripts & CI T-fix Type: Bug fix (in something that's supposed to work already) labels May 20, 2026
@torokati44 torokati44 merged commit 4c2753f into ruffle-rs:master May 20, 2026
26 checks passed
@SuchAFuriousDeath SuchAFuriousDeath deleted the fix-mvp-build branch May 20, 2026 12:21
Hancock33 added a commit to Hancock33/batocera.piboy that referenced this pull request May 23, 2026
------------------------------------------------------------------------------------------
dolphin-emu.mk 57f1dc97e0e94024f3f931ec03dfd4a18811e670 # Version: Commits on May 21, 2026
------------------------------------------------------------------------------------------
Merge pull request #14655 from tom-pratt/gradle-sync-windows-fix

Fix android gradle sync error on windows,

-----------------------------------------------------------------------------------
eden.mk 889545e1ee17ef5e0a88faf18861f47a0e9e7523 # Version: Commits on May 21, 2026
-----------------------------------------------------------------------------------
[common/virtual_buffer] fix technically wrong usage of std::exchange() (#3992)

-------------------------------------------------------------------------------------
ppsspp.mk 3b776e65b710646dae43a6168625312fd07cf59a # Version: Commits on May 21, 2026
-------------------------------------------------------------------------------------
Merge pull request #21718 from hrydgard/matrix-caching

Keep updated products of view*proj and world*view*proj matrices.,

------------------------------------------------------------------------------------
rpcs3.mk 67464f97df8679d5d540256987551f34fe00d4cc # Version: Commits on May 20, 2026
------------------------------------------------------------------------------------
Qt: only allow removal of firmware cache while emulator is stopped,

--------------------------------------------------------------------------------------
shadps4.mk 00339cf0102110e89c6fbb7a17c0d8c56b30940b # Version: Commits on May 21, 2026
--------------------------------------------------------------------------------------
http part6 (#4460)

* added http* epolls

* changed info to debug

* one more info to debug

* helper function,

-------------------------------------------------------------------------------------
snes9x.mk f8aff9cbd0ab3ee92679f039298d57b55f9d790e # Version: Commits on May 20, 2026
-------------------------------------------------------------------------------------
Merge pull request #1053 from shanytc/fix-save-slot-bank-1052

win32: fix save-slot corruption from SelectSave hotkey on bank > 0,

---------------------------------------------------------------------------------------
touchhle.mk 66820ad28efc47e8bc07c8b971fbfcd01bc1dbee # Version: Commits on May 19, 2026
---------------------------------------------------------------------------------------
Implement NSDate copyWithZone:

Change-Id: I593cac9bc7c7c4addcd447d8a7dfb0846373c565,

--------------------------------------------------------------------------------------
tsugaru.mk 18dab94e5148c0e95478dae5dfa9e41096234a5c # Version: Commits on May 21, 2026
--------------------------------------------------------------------------------------
NET tests passes on WSL.,

-------------------------------------------------
vice.mk r46112 # Version: Commits on May 20, 2026
-------------------------------------------------
null

-------------------------------------------------------------------------------------------
xenia-canary.mk b2aa8b200a1ca74f410a8c6ac6d710f2d24e36d5 # Version: Commits on May 20, 2026
-------------------------------------------------------------------------------------------
[BASE] Use FlushAllSinks instead of inline loop,

-----------------------------------------------------------------------------------------
xenia-edge.mk 71dcd5004050e7d1f26c0297e7922e533560dac0 # Version: Commits on May 21, 2026
-----------------------------------------------------------------------------------------
[UI] Add volume controls,

-------------------------------------------------------------------------------------
ikemen.mk b113ac6b9c2752d543eb1a7c5ce7e9c2e9685d46 # Version: Commits on May 21, 2026
-------------------------------------------------------------------------------------
docs: submission guidelines,

---------------------------------------------------------------
ruffle.mk nightly-2026-05-21 # Version: Commits on May 21, 2026
---------------------------------------------------------------
## What's Changed

* video/vp6: Init nihav decoder with encoded size, not display size by @SuchAFuriousDeath in ruffle-rs/ruffle#23665

* web/audio: Pin AudioContext to 44.1 kHz by @SuchAFuriousDeath in ruffle-rs/ruffle#23701

* web: Fix MVP wasm build by explicitly disabling post-MVP features by @SuchAFuriousDeath in ruffle-rs/ruffle#23756

* avm2: Set dobj as transformed_by_script on transform `colorTransform` and `matrix` setters by @ChrisCPI in ruffle-rs/ruffle#23759

* avm2: Return ArgumentError instead of panicking on invalid ShaderJob target by @SuchAFuriousDeath in ruffle-rs/ruffle#23763

* chore: Migrate to current Node.js 26 from 25 for testing by @torokati44 in ruffle-rs/ruffle#23661

* avm2: Print full error details when logging caught error by @Lord-McSweeney in ruffle-rs/ruffle#23726

**Full Changelog**: ruffle-rs/ruffle@nightly-2026-05-20...nightly-2026-05-21,

-----------------------------------------------------------------------------------------
rpi-eeprom.mk 25f837ab8009a643ed85b9aad94d911baddaf0c4 # Version: Commits on Feb 23, 2026
-----------------------------------------------------------------------------------------
rpi-eeprom-update: Check RPI_EEPROM_IMMEDIATE_UPDATE after initialised

See: raspberrypi#809,

----------------------------------------------------------------------------------------
rpi-utils.mk 4dec6508e097fe9ee0450bdd9db0ff8fc5a8bed8 # Version: Commits on May 21, 2026
----------------------------------------------------------------------------------------
ovmerge: String values can en/disable fragments

Allow arbitrary string values to be used to enable and disable fragments

via overlay overrides, e.g <0>,\+1\. This is a convenience, allowing

e.g. a parameter that is writing a string to a property to also enable

the fragment that contains that property, without requiring that the

string has an obvious boolean value such as \true\.

In the event that \=\ and \!\ conditionals are used, a non-empty string

is true and an empty string is false.

This patch mirrors #183.

Signed-off-by: Phil Elwell <phil@raspberrypi.com>,

------------------------------------------------------------------------------------
gl4es.mk ca130307c7be827175131dbd12f8af678f2983f7 # Version: Commits on May 21, 2026
------------------------------------------------------------------------------------
Merge pull request #510 from orbisai0security/fix-v002-array-underflow

array: validate skip/count before array copy sizing,

------------------------------------------------------------------------------------
rtw88.mk a56bcd26e770257612a0803249cbd4095fc6feca # Version: Commits on May 21, 2026
------------------------------------------------------------------------------------
8821a/8812a: Clear BIT_BT_PTA_EN only for USB

It's not supposed to be done for PCI. It causes problems for the

bluetooth part of RTL8812AE.

Signed-off-by: Bitterblue Smith <rtl8821cerfe2@gmail.com>,

------------------------------------------------------------------------------------------
devilutionx.mk 04689419a8d610c9f960164bc4da04f2a23da57b # Version: Commits on May 21, 2026
------------------------------------------------------------------------------------------
Improve Emscripten build (#8312),

-------------------------------------------------------------------------------------------------
shadps4-qtlauncher.mk cb8ba97359810dfe0fb696644306d0def0e4b227 # Version: Commits on May 21, 2026
-------------------------------------------------------------------------------------------------
New Crowdin updates (#360)

* New translations en_us.ts (Russian)

[ci skip]

* New translations en_us.ts (German)

[ci skip]

* New translations en_us.ts (Catalan)

[ci skip]

* New translations en_us.ts (French)

[ci skip]

* New translations en_us.ts (Spanish)

[ci skip]

* New translations en_us.ts (Czech)

[ci skip]

* New translations en_us.ts (Japanese)

[ci skip]

* New translations en_us.ts (Swedish)

[ci skip]

* New translations en_us.ts (Turkish)

[ci skip]

* New translations en_us.ts (Chinese Simplified)

[ci skip]

* New translations en_us.ts (Croatian)

[ci skip]

* New translations en_us.ts (Romanian)

[ci skip]

* New translations en_us.ts (Arabic)

[ci skip]

* New translations en_us.ts (Danish)

[ci skip]

* New translations en_us.ts (Greek)

[ci skip]

* New translations en_us.ts (Finnish)

[ci skip]

* New translations en_us.ts (Hungarian)

[ci skip]

* New translations en_us.ts (Italian)

[ci skip]

* New translations en_us.ts (Korean)

[ci skip]

* New translations en_us.ts (Lithuanian)

[ci skip]

* New translations en_us.ts (Dutch)

[ci skip]

* New translations en_us.ts (Polish)

[ci skip]

* New translations en_us.ts (Portuguese)

[ci skip]

* New translations en_us.ts (Slovenian)

[ci skip]

* New translations en_us.ts (Albanian)

[ci skip]

* New translations en_us.ts (Ukrainian)

[ci skip]

* New translations en_us.ts (Chinese Traditional)

[ci skip]

* New translations en_us.ts (Urdu (Pakistan))

[ci skip]

* New translations en_us.ts (Vietnamese)

[ci skip]

* New translations en_us.ts (Portuguese, Brazilian)

[ci skip]

* New translations en_us.ts (Indonesian)

[ci skip]

* New translations en_us.ts (Persian)

[ci skip]

* New translations en_us.ts (Norwegian Bokmal)

[ci skip]

* New translations en_us.ts (Serbian (Latin))

[ci skip]

* New translations en_us.ts (Portuguese, Brazilian)

[ci skip]

* New translations en_us.ts (German)

[ci skip],

----------------------------------------------------------------------------------------
retroarch.mk 55009f798d2aa9a6e293f6a448f6ded1c1684828 # Version: Commits on May 21, 2026
----------------------------------------------------------------------------------------
Fetch translations from Crowdin,

----------------------------------------------------------
bgfx.mk v1.143.9257-544 # Version: Commits on May 21, 2026
----------------------------------------------------------
deps: bump to latest bgfx,

---------------------------------------------------------------------------------------
vpinball.mk dab4222898e7f7de19d150127e52b939a7059256 # Version: Commits on May 21, 2026
---------------------------------------------------------------------------------------
docs: fix linux settings .local/share typo (@WildCoder) (#3417),

----------------------------------------------------------------------------------------
doomretro.mk bbc19261e86109dc01c26273437b97021089ea49 # Version: Commits on May 21, 2026
----------------------------------------------------------------------------------------
Guard SetProcessInformation for older Windows

https://www.doomworld.com/forum/post/3027454,

------------------------------------------------------------------------------------------
xash3d-fwgs.mk 074bd8b2b37227253a932f19fd601eb95376b093 # Version: Commits on May 19, 2026
------------------------------------------------------------------------------------------
public: add unaligned access handlers for new big endian port,

---------------------------------------------------------------------------------------------------
libretro-dosbox-pure.mk dab7b3fd66669bc2f5e7c54d45c0a7716b1364a1 # Version: Commits on May 21, 2026
---------------------------------------------------------------------------------------------------
Prevent Windows 98 from showing a \Advanced Power Management support\ system device with a yellow exclamation mark in its Device Manager while still supporting automatic exitting of the emulator via guest OS shutdown (#738),

---------------------------------------------------------------------------------------------
libretro-fbneo.mk 42d3c6189b1fb19e0a8ebc8be777c762d6ac434e # Version: Commits on May 21, 2026
---------------------------------------------------------------------------------------------
(libretro) update files,

--------------------------------------------------------------------------------------------------
libretro-gearcoleco.mk 4edd179124ab27157f3acd1893f0eb2bee87ed1e # Version: Commits on May 20, 2026
--------------------------------------------------------------------------------------------------
[libretro] Fix audio with run-ahead single instance. Fix #31,

--------------------------------------------------------------------------------------------------
libretro-gearsystem.mk 803ff97c8fc6820941a0bbad7c1e8af1bab3b465 # Version: Commits on May 20, 2026
--------------------------------------------------------------------------------------------------
[libretro] Fix audio with run-ahead single instance,

----------------------------------------------------------------------------------------------
libretro-ppsspp.mk 3b776e65b710646dae43a6168625312fd07cf59a # Version: Commits on May 21, 2026
----------------------------------------------------------------------------------------------
Merge pull request #21718 from hrydgard/matrix-caching

Keep updated products of view*proj and world*view*proj matrices.,

--------------------------------------------------------------------------------------------
libretro-puae.mk 9fda5f344470d6837e17b939b0f53e5afe938878 # Version: Commits on May 21, 2026
--------------------------------------------------------------------------------------------
Remove gcc16 warnings,

----------------------------------------------------------------------------------------------
libretro-stella.mk 6aedb8114a6a2a9036136ecab8f133c74f4f1c9d # Version: Commits on May 21, 2026
----------------------------------------------------------------------------------------------
Hardening code in FBBackendSDL; checking for nullptr before proceeding in a few cases.,

--------------------------------------------------------------------------------------------
libretro-vice.mk b0d88812a0af0dcba40041d78709480ad1d90833 # Version: Commits on May 21, 2026
--------------------------------------------------------------------------------------------
Correction to previous,
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

A-build Area: Build scripts & CI T-fix Type: Bug fix (in something that's supposed to work already)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Web, build-system] wasm-bindgen errors out on vanilla WASM profile when doing build:dual-wasm

3 participants