nbind icon indicating copy to clipboard operation
nbind copied to clipboard

emscripten support build wasm

Open ErosZy opened this issue 6 years ago • 8 comments

we should add wasm build,and create a load wasm lib to use in browser.

ErosZy avatar Mar 01 '18 16:03 ErosZy

To add some detail, if you install the latest emsdk, emscripten tries to build wasm by default and fails during linking. I found if I replaced node_modules/nbind/src/pre.js and node_modules/nbind/src/post.js with empty files then the link succeeded but I couldn't use the ndts tool. I also haven't tested if the resulting build actually runs. Error log before edited pre.js and post.js:

  LINK(target) Release/nbind.js
warning: unresolved symbol: $SOCKFS
Stack: Error
    at assertTrue (eval at globalEval (/home/edwardb/emsdk/emscripten/1.38.8/tools/js-optimizer.js:114:8), <anonymous>:59:26)
    at Object.emitDCEGraph (/home/edwardb/emsdk/emscripten/1.38.8/tools/js-optimizer.js:8165:3)
    at /home/edwardb/emsdk/emscripten/1.38.8/tools/js-optimizer.js:8389:14
    at Array.forEach (<anonymous>)
    at Object.<anonymous> (/home/edwardb/emsdk/emscripten/1.38.8/tools/js-optimizer.js:8388:21)
    at Module._compile (module.js:635:30)
    at Object.Module._extensions..js (module.js:646:10)
    at Module.load (module.js:554:32)
    at tryModuleLoad (module.js:497:12)
    at Function.Module._load (module.js:489:3)

undefined:60
    throw msg;
    ^
Assertion failed: could not find the assigment to "asmLibraryArg". perhaps --pre-js or --post-js code moved it out of the global scope? (things like that should be done after emcc runs, as they do not need to be run through the optimizer which is the special thing about --pre-js/--post-js code)
Traceback (most recent call last):
  File "/home/edwardb/emsdk/emscripten/1.38.8/emcc", line 11, in <module>
    python_selector.run(__file__)
  File "/home/edwardb/emsdk/emscripten/1.38.8/tools/python_selector.py", line 38, in run
    sys.exit(run_by_import(filename, main) if on_allowed_version() else run_by_subprocess(filename))
  File "/home/edwardb/emsdk/emscripten/1.38.8/tools/python_selector.py", line 13, in run_by_import
    return getattr(importlib.import_module(os.path.basename(filename)), main)()
  File "/home/edwardb/emsdk/emscripten/1.38.8/emcc.py", line 2019, in run
    wasm_text_target, misc_temp_files, optimizer)
  File "/home/edwardb/emsdk/emscripten/1.38.8/emcc.py", line 2559, in do_binaryen
    emit_symbol_map=emit_symbol_map)
  File "/home/edwardb/emsdk/emscripten/1.38.8/tools/shared.py", line 2481, in minify_wasm_js
    js_file = Building.metadce(js_file, wasm_file, minify_whitespace=minify_whitespace, debug_info=debug_info)
  File "/home/edwardb/emsdk/emscripten/1.38.8/tools/shared.py", line 2501, in metadce
    txt = Building.js_optimizer_no_asmjs(js_file, ['emitDCEGraph', 'noEmitAst'], return_output=True)
  File "/home/edwardb/emsdk/emscripten/1.38.8/tools/shared.py", line 2344, in js_optimizer_no_asmjs
    return run_process(NODE_JS + [js_optimizer.JS_OPTIMIZER, filename] + passes, stdout=PIPE).stdout
  File "/home/edwardb/emsdk/emscripten/1.38.8/tools/shared.py", line 162, in run_process
    return run_base(cmd, universal_newlines=universal_newlines, check=check, *args, **kw)
  File "/home/edwardb/emsdk/emscripten/1.38.8/tools/shared.py", line 157, in run_base
    result.check_returncode()
  File "/home/edwardb/emsdk/emscripten/1.38.8/tools/shared.py", line 143, in check_returncode
    raise Py2CalledProcessError(returncode=self.returncode, cmd=self.args, output=self.stdout, stderr=self.stderr)
tools.shared.Py2CalledProcessError: Command '['/home/edwardb/emsdk/node/8.9.1_64bit/bin/node', '/home/edwardb/emsdk/emscripten/1.38.8/tools/js-optimizer.js', '/tmp/tmpzAdoW8/nbind.bc.o.js.pp.js.mem.js.jso.js', 'emitDCEGraph', 'noEmitAst']' returned non-zero exit status 1
nbind.target.mk:512: recipe for target 'Release/nbind.js' failed
make: *** [Release/nbind.js] Error 1

ed-alertedh avatar Jul 11 '18 03:07 ed-alertedh

I think if you run node-gyp configure and then edit build/Makefile you can add -s WASM=0 to the cmd_link configuration. I got it to produce nbind.js and nbind.js.mem rather than nbind.js + a wasm file.

william-silversmith avatar Jul 11 '18 19:07 william-silversmith

@william-silversmith you should also be able to add "cflags": ["-s WASM=0"] to your binding.gyp file. It would be nice to have the option to generate a working wasm build too though.

edit: even with WASM=0 I still get the errors about pre-js and post-js

ed-alertedh avatar Jul 12 '18 00:07 ed-alertedh

@ed-alertedh That didn't work for me unfortunately. It still produces WASM.

william-silversmith avatar Jul 17 '18 23:07 william-silversmith

I'm still seeing errors on pre/post js files relating to this. Has anyone made any progress?

holsted avatar Aug 30 '18 13:08 holsted

Looks like it's related to this - https://github.com/Kagami/ffmpeg.js/issues/44#issuecomment-392248729

holsted avatar Aug 30 '18 15:08 holsted

I ended up running into enough issues with nbind's default gypi configuration that I made my own copy of nbind.gypi and included that instead of including auto.gypi. This allowed me to have full control over the cflags, the pre and post js, whether FS emulation is enabled, etc. I still couldn't get WASM to work due to errors when my C++ code tried to access the filesystem. It looked like the WASM was trying to access the FS_* functions in the module and they weren't present. It's possible that the module init code needs to be changed to work with wasm. Although iirc I ran into similar issues when I tried to output asm.js with the latest emscripten. The workaround for now was to use the emscripten binaries used in nbind's CI build. I know it's probably off-topic but if it's useful for anyone, this is the Dockerfile I'm using:

FROM debian:latest

RUN apt-get update && apt-get install -y --no-install-recommends \
    ca-certificates \
    build-essential\
    curl \
    git-core \
    openjdk-8-jre-headless \
    python \
    wget \
    gnupg \
    git \
    && apt-mark hold openjdk-8-jre-headless \
    && apt-mark hold make \
    && curl -sL https://deb.nodesource.com/setup_6.x | bash - \
    && apt-get install -y nodejs

ENV TOOLS_PATH="/tools"
WORKDIR /tools

RUN git clone --depth=1 https://github.com/charto/emscripten-ci-linux-binary.git emscripten
RUN ./emscripten/emsdk activate --build=Release sdk-master-64bit
# env vars based on running: source ./emsdk_env.sh
# Adding directories to PATH:
ENV PATH="${TOOLS_PATH}/emscripten:${PATH}"
ENV PATH="${TOOLS_PATH}/emscripten/clang/fastcomp/build_master_64/bin:${PATH}"
ENV PATH="${TOOLS_PATH}/emscripten/node/4.1.1_64bit/bin:${PATH}"
ENV PATH="${TOOLS_PATH}/emscripten/emscripten/master:${PATH}"

# Setting environment variables:
ENV EM_CONFIG="/root/.emscripten"
ENV EMSCRIPTEN="${TOOLS_PATH}/emscripten/emscripten/master"

RUN emcc --version \
    && mkdir -p /tmp/emscripten_test && cd /tmp/emscripten_test \
    && printf '#include <iostream>\nint main(){std::cout<<"HELLO"<<std::endl;return 0;}' > test.cpp \
    && em++ -O2 test.cpp -o test.js && nodejs test.js \
    && em++ test.cpp -o test.js && nodejs test.js \
    && cd / \
    && rm -rf /tmp/emscripten_test

RUN npm install -g yarn
VOLUME ["/src"]
WORKDIR /src

ed-alertedh avatar Sep 03 '18 02:09 ed-alertedh

Skipping the gyp based build instructions, I made my own CMake build based on https://groups.google.com/g/emscripten-discuss/c/LPMLVl-XcHQ/m/IBBDhR_LAAAJ, and I could successfully target WASM with that.

mmarczell-graphisoft avatar Dec 03 '21 14:12 mmarczell-graphisoft