nbind
nbind copied to clipboard
emscripten support build wasm
we should add wasm build,and create a load wasm lib to use in browser.
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
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 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 That didn't work for me unfortunately. It still produces WASM.
I'm still seeing errors on pre/post js files relating to this. Has anyone made any progress?
Looks like it's related to this - https://github.com/Kagami/ffmpeg.js/issues/44#issuecomment-392248729
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
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.