WASM: wire it up! #33
Labels
No Label
accepted
bug
clj
documentation
enhancement
errors
infrastructure
later
next
now
optimization
proposal
question
research
semantics
syntax
ux
vm
wontfix
No Milestone
No project
2 Participants
Notifications
Due Date
No due date set.
Dependencies
No dependencies set.
Reference: twc/ludus#33
Loading…
Reference in New Issue
Block a user
No description provided.
Delete Branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Janet + WASM = ❤️🩹?
Guide: https://janet.guide/embedding-janet/
Example: https://toodle.studio
@matt Can you look into this and clear the way?
Okay. I figured out how to do this, more or less.
Zig is great, but its build system is very powerful, very complicated and seriously under-documented.
(See, e.g., https://ziggit.dev/t/building-wasm-with-dependencies/4362.)
I've successfully generated a
.wasm
bundle; I haven't wired it up to JS yet; it may not work. But it works as expected when compiled to native code on my Mac.Just to document here where I am and what I've done:
jzignet
in as a dependency only ever compiled the Zig, even withjanet.c
andjanet.h
as explicit dependencies.jzignet
's C dependencies were being requested as JS environment functions, so Node threw errors like, "janet_unwrap_string
must be callable." I added all the "callable" functions to the JS/WASM environment and indeed, they were dutifully called. But notably not Janet's c-functions.jzignet.zig
,janet.h
,janet.c
, and compiled everything with awasm32-freestanding
(or, for that matter,wasm32-wasi
) target.Here's what I get:
So: Janet's interpreter depends on
setjmp.h
, apparently? And WASM doesn't like this. Apparently it's some kind of C-level iteration ofjmp
orlongjmp
assembly instructions which WASM doesn't have.And thus: it looks like Zig's WASM integration won't/can't compile Janet.
Emscripten, however, will. That does mean using C/C++ instead of Zig as the host language.
So two paths forward at this point:
(1) is preferable in the long run; (2) is perhaps more tractable. IanTheHenry's https://toodle.studio/ uses Emscripten, and I think we can hack what's in that repo down to manageable size by deleting everything, getting a minimal compile, and then adding things back in until we have what we need for Ludus.
A more direct way to arrive at the error above:
Found another interesting example using emscripten: https://github.com/sogaiu/jaylib-wasm-demo/blob/master/main.c
Taking notes on how to wire up a Janet+WASM environment, in broad strokes (repos with various stages forthcoming). Note that this allows passing Javascript strings into Janet and getting them back out without too much fuss.
Create your Janet program. These are all top-level bindings. No main or anything, just the bindings you want & need.
Compile the program with
janet -c source.janet target.jimage
In the CPP driver file (ganked from IanTheHenry's Bauble/Toodle), you will need to accomplish the following:
main
function of the driver, read in and marshal the environment in question, that contains your Janet functionallow_raw_pointers
Build the CPP file using Emscripten. Current invocation is:
Added to the above: getting strings from Janet -> C++ -> JS is not trivial, either. But it's doable!
There may well be a more direct way of going about things, but this is what I got that works:
In JS, then, simply access
.value
on any expected string result.Next up: make a repo with a standalone POC.
It is all up in https://alea.ludus.dev/twc/emscranet
Current state of play:
cd
intobuild
and thenjust build
.build
directory, and cannot be sent somewhere else.package.json
is now updated to point to the new wasp-based interpreter.0.1.0-alpha.10
.