Skip to content

wasm32-emscripten: per-OS descriptor sections fall back to the host's, release links without -O, only JS exceptions #851

Closed

Description

@Sunrisepeak

Found while building openmui's dependencies for wasm32-emscripten (mcpp 2026.10.26.1, emsdk 6.0.9, node 26.7.0). Three engine gaps, in order of impact.

1. An Emscripten build reads the host's per-OS section of a package descriptor

TargetPlatform::for_os (modules/toolchain-model/src/platform.cppm) maps a triple's os through xpkg_platform_key_for, which knows linux, macos(x) and windows; for emscripten it returns nullopt and for_os falls back to the host (value_or(xpkg_platform)).

So on a Linux host a wasm build takes a descriptor's linux block:

  • taskflow.taskflow's Linux -pthread is applied. Without [target.'cfg(os = "emscripten")'.abi] threads = true the link fails with --shared-memory is disallowed, although the program never asked for threads.
  • compat.freetype's Linux sources and flags are compiled into the wasm build.

On a Windows host the same build would take the windows block (e.g. FreeType's builds/windows/ftsystem.c) — inferred from the descriptor and the code above, not run.

Reproduce: a package depending on taskflow.taskflow = "4.1.0" that uses nothing but tf::Taskflow, then mcpp build --target wasm32-emscripten on Linux.

What would fix it: a descriptor key of its own for Emscripten (absent block = the package declares no Emscripten build) instead of the host fallback, so a target never silently inherits the build machine's platform.

2. A release build links without an optimisation level

The link line carries no -O, so emcc skips wasm-opt and leaves the JavaScript launcher unminified. With ldflags = ["-O2"] added for Emscripten:

program wasm (bytes) JS (bytes)
hello world 367,420 → 312,657 65,920 → 13,137
nlohmann.json + tomlplusplus + a small library 733,495 → 534,445 —
harfbuzz, libpng, md4c, fribidi, concurrentqueue 2,450,796 → 2,160,423 —

The profile's optimisation level should reach the link for this target (for emcc the link is where wasm-opt runs).

3. Exceptions: only the JavaScript-based model

[target.'cfg(os = "emscripten")'.abi] exceptions = true selects -fexceptions (JS-based). Native wasm exceptions (-fwasm-exceptions) are smaller and faster and are what a new build should prefer; there is no way to choose them.

Also observed (defaults, perhaps documentation)

Emscripten's defaults are a 64 KiB stack and a fixed 16 MiB heap: a 64 MiB allocation aborts with "OOM", and a 64 KiB buffer on the stack overflows it. ldflags = ["-sALLOW_MEMORY_GROWTH=1", "-sSTACK_SIZE=1048576"] fixes both; worth either a documented recipe or [target.<sel>.abi] keys.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions