Skip to content

Add initial integration with wasm-bindgen#23493

Merged
sbc100 merged 106 commits into
emscripten-core:mainfrom
walkingeyerobot:wbg-walkingeyerobot
Jun 10, 2026
Merged

Add initial integration with wasm-bindgen#23493
sbc100 merged 106 commits into
emscripten-core:mainfrom
walkingeyerobot:wbg-walkingeyerobot

Conversation

@walkingeyerobot

@walkingeyerobot walkingeyerobot commented Jan 24, 2025

Copy link
Copy Markdown
Collaborator

This is an early draft PR for the purposes of gathering feedback early. There are also pending changes to wasm-bindgen. This is ready for review.

How this works:

  1. Cargo builds Rust code targeting wasm32-unknown-emscripten into a .a file (staticlib). This .a file includes some annotations needed by wasm-bindgen later.
  2. Emscripten is invoked with any C++ sources and the Rust .a file.
  3. Emscripten builds C++ sources and then calls out to wasm-ld to link the C++ and Rust together into a single .wasm file.
  4. wasm-bindgen is run on that .wasm file, removing the annotations needed by wasm-bindgen and producing a new .wasm file, a library.js file, and a pre.js file.
  5. Emscripten constructs its own .js, integrating the wasm-bindgen .js files.

You can see a demo more easily at https://github.com/walkingeyerobot/cxx-rust-demo.

Some TODOs:

  1. Figure out how to pass the exported symbols from the rust compiler to Emscripten. These are symbols that need to be passed to wasm-ld so they're not removed in the final .wasm but that may not necessarily be present after wasm-bindgen processes the .wasm. wasm-bindgen at compile time puts the information it needs to generate JS inside the .wasm file itself in the form of _describe functions. These functions are then removed after JS generation.
  2. Merge the .js files produced by wasm-bindgen. This shouldn't be that hard; I just haven't gotten around to it yet. This would simplify the code for both Emscripten and wasm-bindgen.
  3. Get wasm-bindgen tests to pass. Early efforts here have revealed some very odd compiler differences between -unknown and -emscripten that I'll have to fix.
  4. Have this work end-to-end via wasm-pack. I'll have a draft PR for this soon (tm). My work here didn't pan out, but there's a new PR for this here: feat: support wasm32-unknown-emscripten target wasm-bindgen/wasm-pack#1583

I'm mostly looking for feedback on the first point about exported symbols and about the general addition of -sWASM_BINDGEN to Emscripten. Again, this is very early, but it's a pretty big feature, so I thought it best to start discussions now.

cc @daxpedda @guybedford @RReverser, who I've been working with on the wasm-bindgen side.

(updated May 18 2026 to be more accurate as to the current state of things)

@kripken

kripken commented Jan 24, 2025

Copy link
Copy Markdown
Member

wasm-bindgen at compile time puts the information it needs to generate JS inside the .wasm file itself in the form of _describe functions.

Does rustc then read the wasm to find those function names, and pass those names to wasm-ld? (if not, how does it find those names?)

In general if we need to read metadata-type info from the wasm, then we have a minimal parser in tools/webassembly.py. If we need something more complex, a binaryen pass is an option.

@walkingeyerobot

Copy link
Copy Markdown
Collaborator Author

wasm-bindgen itself is two pieces: a library that allows you to annotate your rust code marking things to be exported, and a tool that consumes a .wasm file and reads those annotations to produce a companion js file. rustc knows about those function names because wasm-bindgen as a library provided the annotations. If rustc invokes the linker itself, it's able to pass that information along. However, because we need to also build C++, we're only using rustc to compile and not drive the whole process, so we need to have it output that information elsewhere.

One (very naive) possibility is to have rustc invoke a fake linker that just writes the -sEXPORTED_FUNCTIONS to a file for emscripten to read later.

Comment thread tools/link.py Outdated
Comment thread tools/link.py Outdated
Comment thread tools/building.py Outdated
Comment thread tools/building.py Outdated
Comment thread tools/building.py Outdated
Comment thread tools/building.py Outdated
Comment thread test/test_other.py Outdated
Comment thread tools/building.py Outdated
Comment thread tools/building.py Outdated
return run_binaryen_command('wasm-opt', infile, outfile, args=args, **kwargs)


def run_wasm_bindgen(infile, outfile=None, args=[], **kwargs): # noqa

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

This only has a single caller which only passes one argument so I think we can just remove all the other arguments here?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Done.

Comment thread tools/link.py Outdated
Comment thread tools/link.py Outdated
Comment thread src/runtime_common.js Outdated
Comment thread tools/link.py Outdated
Comment thread tools/link.py Outdated
Comment thread tools/utils.py Outdated
@sbc100

sbc100 commented Jun 9, 2026

Copy link
Copy Markdown
Collaborator

Codesize failures probably just mean you need a rebase/merge.

@sbc100 sbc100 changed the title Add wasm-bindgen support Add initial integration with wasm-bindgen Jun 9, 2026
Comment thread tools/link.py
Comment thread tools/cmdline.py Outdated

@sbc100 sbc100 left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

What would you like the comment message to look like? Do you want to update the PR description with that, or write it in a comment?

@walkingeyerobot

Copy link
Copy Markdown
Collaborator Author

What would you like the comment message to look like? Do you want to update the PR description with that, or write it in a comment?

Something like this? Feel free to edit.

Adds wasm-bindgen support. When -sWASM_BINDGEN is set, Emscripten will call out to wasm-bindgen in the users's path and integrate the wasm-bindgen JS with the normal Emscripten JS. Some wasm-bindgen features may not yet be fully supported.

@sbc100

sbc100 commented Jun 9, 2026

Copy link
Copy Markdown
Collaborator

Actually now that I think about it this should probably also come with a ChangeLog entry..

@walkingeyerobot

Copy link
Copy Markdown
Collaborator Author

I added a ChangeLog entry.

Comment thread ChangeLog.md Outdated
----------------------
- The `-sUSE_PTHREADS` and `-sMEMORY64` flags have been deprecated in favor of the
more standard `-pthread` and `-m64` (or `--target=wasm64`) flags. (#27025)
- Adds wasm-bindgen support. When `-sWASM_BINDGEN` is set, Emscripten will call out to `wasm-bindgen` in the users's path and integrate the wasm-bindgen JS with the normal Emscripten JS. Some wasm-bindgen features may not yet be fully supported.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Sorry to be a pain, can you wrap this at 80 cols.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Done.

Comment thread ChangeLog.md Outdated
----------------------
- The `-sUSE_PTHREADS` and `-sMEMORY64` flags have been deprecated in favor of the
more standard `-pthread` and `-m64` (or `--target=wasm64`) flags. (#27025)
- Adds wasm-bindgen support. When `-sWASM_BINDGEN` is set, Emscripten will call out to `wasm-bindgen` in the users's path and integrate the wasm-bindgen JS with the normal Emscripten JS. Some wasm-bindgen features may not yet be fully supported.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

And add (#23493) to the end of the line

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Done.

@sbc100 sbc100 merged commit bdd20af into emscripten-core:main Jun 10, 2026
39 checks passed
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.

6 participants