wasmerio / wasmer

🚀 The leading Wasm Runtime supporting WASIX, WASI and Emscripten
https://wasmer.io
MIT License
18.21k stars 767 forks source link

Clarifications on emscripten support. #3110

Closed apollo13 closed 1 day ago

apollo13 commented 1 year ago

Describe the bug

I am trying to execute a empscripten compiled binary and I am getting the following error:

error: failed to run `libmupdf.wasm`
╰─▶ 1: Error while importing "env"."getTempRet0": unknown import. Expected Function(FunctionType { params: [], results: [I32] })
 echo "`wasmer -v` | `rustc -V` | `uname -m`"
error: Found argument '-v' which wasn't expected, or isn't valid in this context

    If you tried to supply `-v` as a value rather than a flag, use `-- -v`

USAGE:
    wasmer [OPTIONS] <FILE> [ARGS]...

For more information try --help
 | rustc 1.60.0 (7737e0b5c 2022-04-04) | x86_64

not sure what the correct argument is to get the wasmer version but it is 3.0.0-beta

Steps to reproduce

Build a wasm project with -s WASM -s STANDALONE_WASM -s PURE_WASI to actually get a WASI (somewhat) binary. In my case I was compiling using the instructions here: https://github.com/ArtifexSoftware/mupdf/tree/master/platform/wasm

Run the binary with wasmer and observe the above error.

Expected behavior

Wasmer should successfully execute the binary or provide a better error message (maybe even just a documentation update would help)

Additional context

Wasmer inspect shows:

Type: wasm
Size: 4.6 MB
Imports:
  Functions:
    "env"."getTempRet0": [] -> [I32]
    "env"."setTempRet0": [I32] -> []
    "env"."invoke_vii": [I32, I32, I32] -> []
    "env"."invoke_iii": [I32, I32, I32] -> [I32]
    "env"."invoke_iiii": [I32, I32, I32, I32] -> [I32]
    "env"."invoke_viiii": [I32, I32, I32, I32, I32] -> []
    "env"."invoke_viii": [I32, I32, I32, I32] -> []
    "env"."invoke_ii": [I32, I32] -> [I32]
    "env"."invoke_vi": [I32, I32] -> []
    "env"."invoke_iiiii": [I32, I32, I32, I32, I32] -> [I32]
    "env"."invoke_viiiii": [I32, I32, I32, I32, I32, I32] -> []
    "env"."invoke_iiiiii": [I32, I32, I32, I32, I32, I32] -> [I32]
    "env"."invoke_viiiiii": [I32, I32, I32, I32, I32, I32, I32] -> []
    "env"."invoke_iiiiiii": [I32, I32, I32, I32, I32, I32, I32] -> [I32]
    "env"."invoke_fiii": [I32, I32, I32, I32] -> [F32]
    "env"."invoke_viiiiiii": [I32, I32, I32, I32, I32, I32, I32, I32] -> []
    "env"."invoke_viiff": [I32, I32, I32, F32, F32] -> []
    "env"."invoke_iiiiiiii": [I32, I32, I32, I32, I32, I32, I32, I32] -> [I32]
    "env"."invoke_viiiiiiii": [I32, I32, I32, I32, I32, I32, I32, I32, I32] -> []
    "env"."invoke_viiiiff": [I32, I32, I32, I32, I32, F32, F32] -> []
    "env"."invoke_fii": [I32, I32, I32] -> [F32]
    "env"."invoke_viid": [I32, I32, I32, F64] -> []
    "env"."invoke_iiiiiiiii": [I32, I32, I32, I32, I32, I32, I32, I32, I32] -> [I32]
    "env"."invoke_viif": [I32, I32, I32, F32] -> []
    "env"."invoke_viiiiiiifi": [I32, I32, I32, I32, I32, I32, I32, I32, F32, I32] -> []
    "env"."invoke_viiffff": [I32, I32, I32, F32, F32, F32, F32] -> []
    "env"."invoke_viiiiiiiiiiiii": [I32, I32, I32, I32, I32, I32, I32, I32, I32, I32, I32, I32, I32, I32] -> []
    "env"."invoke_viiiiiiif": [I32, I32, I32, I32, I32, I32, I32, I32, F32] -> []
    "env"."invoke_viiiifi": [I32, I32, I32, I32, I32, F32, I32] -> []
    "env"."invoke_fiiii": [I32, I32, I32, I32, I32] -> [F32]
    "env"."invoke_viiffffff": [I32, I32, I32, F32, F32, F32, F32, F32, F32] -> []
    "env"."invoke_viiiiiiiii": [I32, I32, I32, I32, I32, I32, I32, I32, I32, I32] -> []
    "env"."invoke_viiiiiiiiii": [I32, I32, I32, I32, I32, I32, I32, I32, I32, I32, I32] -> []
    "env"."invoke_viiiiiifi": [I32, I32, I32, I32, I32, I32, I32, F32, I32] -> []
    "env"."invoke_viiif": [I32, I32, I32, I32, F32] -> []
    "env"."invoke_iiiiiiiiiii": [I32, I32, I32, I32, I32, I32, I32, I32, I32, I32, I32] -> [I32]
    "env"."emscripten_asm_const_int": [I32, I32, I32] -> [I32]
    "env"."invoke_iiiiiffi": [I32, I32, I32, I32, I32, F32, F32, I32] -> [I32]
    "env"."invoke_iiiiiiiiii": [I32, I32, I32, I32, I32, I32, I32, I32, I32, I32] -> [I32]
    "env"."invoke_viiiiiiifiiifffffiii": [I32, I32, I32, I32, I32, I32, I32, I32, F32, I32, I32, I32, F32, F32, F32, F32, F32, I32, I32, I32] -> []
    "env"."invoke_iiiiiiiiiiiiii": [I32, I32, I32, I32, I32, I32, I32, I32, I32, I32, I32, I32, I32, I32] -> [I32]
    "env"."invoke_fiiiii": [I32, I32, I32, I32, I32, I32] -> [F32]
    "env"."invoke_iiiffffiii": [I32, I32, I32, F32, F32, F32, F32, I32, I32, I32] -> [I32]
    "wasi_snapshot_preview1"."fd_close": [I32] -> [I32]
    "wasi_snapshot_preview1"."fd_write": [I32, I32, I32, I32] -> [I32]
    "env"."invoke_viifffiiff": [I32, I32, I32, F32, F32, F32, I32, I32, F32, F32] -> []
    "env"."invoke_viiiiifii": [I32, I32, I32, I32, I32, I32, F32, I32, I32] -> []
    "env"."invoke_iiiiiffiifiii": [I32, I32, I32, I32, I32, F32, F32, I32, I32, F32, I32, I32, I32] -> [I32]
    "env"."invoke_viiifffffiii": [I32, I32, I32, I32, F32, F32, F32, F32, F32, I32, I32, I32] -> []
    "env"."invoke_iiiifi": [I32, I32, I32, I32, F32, I32] -> [I32]
    "env"."invoke_viifi": [I32, I32, I32, F32, I32] -> []
    "env"."invoke_viiiif": [I32, I32, I32, I32, I32, F32] -> []
    "env"."invoke_viifff": [I32, I32, I32, F32, F32, F32] -> []
    "env"."invoke_viiffii": [I32, I32, I32, F32, F32, I32, I32] -> []
    "env"."invoke_iif": [I32, I32, F32] -> [I32]
    "env"."invoke_iiiffiiiiiii": [I32, I32, I32, F32, F32, I32, I32, I32, I32, I32, I32, I32] -> [I32]
    "env"."invoke_iiiiifiiii": [I32, I32, I32, I32, I32, F32, I32, I32, I32, I32] -> [I32]
    "env"."invoke_iiiiiffii": [I32, I32, I32, I32, I32, F32, F32, I32, I32] -> [I32]
    "env"."invoke_iiiiij": [I32, I32, I32, I32, I32, I32, I32] -> [I32]
    "env"."invoke_iiij": [I32, I32, I32, I32, I32] -> [I32]
    "env"."invoke_jiij": [I32, I32, I32, I32, I32] -> [I32]
    "env"."invoke_viiij": [I32, I32, I32, I32, I32, I32] -> []
    "env"."invoke_viiji": [I32, I32, I32, I32, I32, I32] -> []
    "env"."invoke_iij": [I32, I32, I32, I32] -> [I32]
    "env"."invoke_viij": [I32, I32, I32, I32, I32] -> []
    "env"."invoke_iiiiiiji": [I32, I32, I32, I32, I32, I32, I32, I32, I32] -> [I32]
    "env"."invoke_iiiiiiiij": [I32, I32, I32, I32, I32, I32, I32, I32, I32, I32] -> [I32]
    "env"."invoke_iiijj": [I32, I32, I32, I32, I32, I32, I32] -> [I32]
    "env"."invoke_jii": [I32, I32, I32] -> [I32]
    "env"."invoke_vij": [I32, I32, I32, I32] -> []
    "env"."_emscripten_throw_longjmp": [] -> []
    "env"."__syscall_stat64": [I32, I32] -> [I32]
    "env"."__syscall_rmdir": [I32] -> [I32]
    "env"."__syscall_unlinkat": [I32, I32, I32] -> [I32]
    "wasi_snapshot_preview1"."fd_seek": [I32, I64, I32, I32] -> [I32]
    "wasi_snapshot_preview1"."environ_get": [I32, I32] -> [I32]
    "wasi_snapshot_preview1"."environ_sizes_get": [I32, I32] -> [I32]
    "wasi_snapshot_preview1"."fd_read": [I32, I32, I32, I32] -> [I32]
    "wasi_snapshot_preview1"."proc_exit": [I32] -> []
    "wasi_snapshot_preview1"."clock_time_get": [I32, I64, I32] -> [I32]
    "env"."emscripten_notify_memory_growth": [I32] -> []
    "env"."invoke_iiiiifffiiii": [I32, I32, I32, I32, I32, F32, F32, F32, I32, I32, I32, I32] -> [I32]
    "env"."invoke_fiiifiif": [I32, I32, I32, I32, F32, I32, I32, F32] -> [F32]
    "env"."invoke_iiiiiiifi": [I32, I32, I32, I32, I32, I32, I32, F32, I32] -> [I32]
    "env"."invoke_viiid": [I32, I32, I32, I32, F64] -> []
    "env"."invoke_iiiif": [I32, I32, I32, I32, F32] -> [I32]
    "env"."invoke_viiiiiiiiiii": [I32, I32, I32, I32, I32, I32, I32, I32, I32, I32, I32, I32] -> []
    "env"."invoke_iiiiiiiiiiiiiiiii": [I32, I32, I32, I32, I32, I32, I32, I32, I32, I32, I32, I32, I32, I32, I32, I32, I32] -> [I32]
    "env"."invoke_iiidi": [I32, I32, I32, F64, I32] -> [I32]
    "env"."js_open_fetch": [I32, I32, I32, I32, I32] -> []
  Memories:
  Tables:
  Globals:
Exports:
  Functions:
    "hack": [] -> []
    "initContext": [] -> []
    "openDocumentFromBuffer": [I32, I32, I32] -> [I32]
    "malloc": [I32] -> [I32]
    "free": [I32] -> []
    "openDocumentFromStream": [I32, I32] -> [I32]
    "freeDocument": [I32] -> []
    "countPages": [I32] -> [I32]
    "pageText": [I32, I32, F32] -> [I32]
    "doDrawPageAsPNG": [I32, I32, F32] -> []
    "getLastDrawData": [] -> [I32]
    "getLastDrawSize": [] -> [I32]
    "pageWidth": [I32, I32, F32] -> [I32]
    "pageHeight": [I32, I32, F32] -> [I32]
    "pageLinks": [I32, I32, F32] -> [I32]
    "search": [I32, I32, F32, I32] -> [I32]
    "documentTitle": [I32] -> [I32]
    "loadOutline": [I32] -> [I32]
    "freeOutline": [I32] -> []
    "outlineTitle": [I32] -> [I32]
    "outlinePage": [I32, I32] -> [I32]
    "outlineDown": [I32] -> [I32]
    "outlineNext": [I32] -> [I32]
    "onFetchData": [I32, I32, I32, I32] -> []
    "openURL": [I32, I32, I32, I32] -> [I32]
    "_initialize": [] -> []
    "setThrew": [I32, I32] -> []
    "stackSave": [] -> [I32]
    "stackRestore": [I32] -> []
    "stackAlloc": [I32] -> [I32]
  Memories:
    "memory": not shared (256 pages..32768 pages)
  Tables:
    "__indirect_function_table": FuncRef (3017..3017)
  Globals:

I realize that wasmer might not detect this properly because the check for emscripten (at least if I am reading the code correctly in https://github.com/wasmerio/wasmer/blame/00c94019d746880daac2f92a2d198ee677ee1e14/lib/emscripten/src/utils.rs#L13-L27) only checks for imports called _emscripten_memcpy_big or __map_file which do not seem to get used anymore. I tried to create a file including those imports, but failed to generate such a file (not sure if emscripten creates files with those at all nowadays).

Please note that I am not saying that wasmer should support emscripten, but it would help users to get started if wasmer provided a better error.

jcaesar commented 1 year ago

I'm curious, what version of emscripten did you use to build your binary? When I investigated a while ago, 1.38.43 was the last version that would work (but that's when used together with Rust, so it might play out differently when invoking emscripten directly).
[Edit:] Looking over it a bit, there's one function that's definitely a problem. But in any case, mupdf is a viewer, right? Iirc, wasmer's emscripten support doesn't allow for any graphics output. (Side note: You might have a better time trying to compile a non-js-targeting version with wasi-sdk.)

apollo13 commented 1 year ago

Hi @jcaesar, thank you for the kind reply. I used 3.1.18 and 3.1.11 iirc (certainly something newer than you used).

[Edit:] Looking over it a bit, there's one function that's definitely a problem.

Oh, makes sense, I'll remove it and see what that brings

EDIT:// not much, getTempRet0 is still in the imports.

But in any case, mupdf is a viewer, right? Iirc, wasmer's emscripten support doesn't allow for any graphics output.

First and foremost it is a library, you give it a bytestream with a pdf and get back a bytestream with a graphic, so I guess support for graphics output should be relatively irrelevant.

Side note: You might have a better time trying to compile a non-js-targeting version with wasi-sdk.

Good point, I'll clean up the wrapper as needed. That said I cannot use wasi-sdk because it does not support exceptions or setlongjmp and as such refuses to compile.

epilys commented 1 year ago

Emscripten support is not complete, and we're working on to define whether we will implement it or not. Emscripten imports have involved since it was last supported in wasmer, and we are not working on this at the moment.

jcaesar commented 1 year ago

Related but very old issue: https://github.com/wasmerio/wasmer/issues/577

liudonghua123 commented 1 year ago

I have a similar problems when trying to build a wasi compatible diff using emscripten. See https://github.com/Lessica/WasmGNUDiff/issues/1.

stale[bot] commented 1 month ago

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

stale[bot] commented 1 day ago

Feel free to reopen the issue if it has been closed by mistake.