dotnet / dotnet/runtime

NativeFileReference-ing a wasm32-unknown-emscripten staticlib built with rustc >= 1.87 fails native relink: Unknown option '--enable-bulk-memory-opt'

Open
#132,858 1 comment 0 reactions 0 assignees View on GitHub
area-Build-mono untriaged
Dominant language
C#
Stars
18.3k
Forks
5.6k
PR merge metrics
PR metrics pending

Description

### Description

Referencing a `wasm32-unknown-emscripten` static library built by a modern Rust toolchain (rustc >= 1.87) via `` in a Blazor WebAssembly project fails the native relink step (triggered automatically by `NativeFileReference`) with:

```
Unknown option '--enable-bulk-memory-opt'
emcc : error : '.../tools/bin/wasm-opt --strip-target-features --post-emscripten -O2 ... --enable-bulk-memory --enable-bulk-memory-opt ...' failed (returned 1)
```

Root cause: rustc >= 1.87's LLVM backend emits WASM target-feature metadata that Binaryen's `wasm-opt` only learned to honor starting with Emscripten 3.1.74. The `wasm-tools` workload's bundled Emscripten is older than that on every SDK band I checked (3.1.56 on the .NET 10 LTS band, bundled `wasm-opt` reports itself as version 117) — squarely inside the broken range.

This is not .NET-specific — an unrelated project (PyO3/maturin, building Python wheels for `wasm32-unknown-emscripten`) hit and diagnosed the identical error independently: [PyO3/maturin#2549](https://github.com/PyO3/maturin/issues/2549). Their thread confirms the same characterization: "incompatibility between rust >= 1.87-nightly and emscripten < 3.1.74."

### Reproduction Steps

Minimal repro — no HyperUuid-specific code involved, a trivial exported function reproduces it:

**`lib.rs`** (staticlib):
```rust
#[unsafe(no_mangle)]
pub extern "C" fn add(a: i32, b: i32) -> i32 {
a + b
}
```

**`Cargo.toml`**:
```toml
[package]
name = "minimal-repro"
version = "0.1.0"
edition = "2024"

[lib]
crate-type = ["staticlib"]
```

Build it:
```bash
rustup target add wasm32-unknown-emscripten
# emcc on PATH via a standalone emsdk (git clone emscripten-core/emsdk, ./emsdk install latest && ./emsdk activate latest, source emsdk_env.sh) — needed as the linker for this target.
cargo build --release --target wasm32-unknown-emscripten
```

Reference the resulting `target/wasm32-unknown-emscripten/release/libminimal_repro.a` from a standard `dotnet new blazorwasm` project via:
```xml

```

`dotnet build -c Release` fails with the error above.

### Expected behavior

The build succeeds — Rust is a first-class, common source of `wasm32-unknown-emscripten` static libraries for `NativeFileReference` scenarios, and rustc 1.87 is not new (released 2025).

### Actual behavior

Build fails with `Unknown option '--enable-bulk-memory-opt'` during the automatic native relink `NativeFileReference` triggers.

### Workaround (verified)

Replacing the bundled `wasm-opt` binary (`$(EmscriptenSdkToolsPath)bin/wasm-opt` — physically at `~/.dotnet/packs/Microsoft.NET.Runtime.Emscripten..Sdk.//tools/bin/wasm-opt`) with a newer one (I used a standalone `emsdk install latest`'s `wasm-opt`, which reports version 132) fixes the build completely — confirmed both on `linux-arm64` and `linux-x64` (via GitHub Actions `ubuntu-latest`), and confirmed both the *failure* and the *fix* against the exact same minimal repro above. `Microsoft.NET.Runtime.Emscripten.Sdk`'s own props (`Sdk.props`) set `EmscriptenSdkToolsPath` unconditionally from the pack's own install directory with no way to override it via MSBuild properties (`EMSDK_PATH`/`EmscriptenSdkToolsPath` set on the command line get silently overwritten) — the physical binary swap is the only lever that actually works.

I don't think patching a user's installed SDK pack is a reasonable long-term answer for consumers — bumping the bundled Emscripten version (or independently updating just the bundled Binaryen/`wasm-opt`) seems like the real fix.

### Versions

- `dotnet --version`: `10.0.400` (also reproduced on the `11.0.100-preview.7` band, bundling Emscripten `6.0.2`/`wasm-opt` — same error, different sub-versions)
- `dotnet workload list` (`wasm-tools`): `10.0.111/10.0.100`, `SDK 10.0.400`
- Bundled `wasm-opt --version`: `117` (Emscripten 3.1.56 pack)
- `rustc --version`: `1.97.1 (8bab26f4f 2026-07-14)`
- Host: `linux-arm64` (WSL2) and `linux-x64` (GitHub Actions `ubuntu-latest`), both reproduce identically

Contributor guide

Open the contributing guide

Research direction

Start with the Microsoft.NET.Runtime.Emscripten.Sdk pack's Sdk.props and its EmscriptenSdkToolsPath assignment, then reproduce the failure using the minimal Rust staticlib and NativeFileReference example. Compare the bundled wasm-opt version and the newer standalone binary; done means the native relink succeeds without requiring users to replace files in the installed SDK pack.

Written by the indexing model from the issue text.

Assessment

Tech stack
rust, wasm
Domain
build-system, tooling
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Active
Clarity
Mostly clear
Newbie friendliness
48/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.