emscripten-core / emscripten

Emscripten: An LLVM-to-WebAssembly Compiler
Other
25.75k stars 3.3k forks source link

Node V14 with CommonJS #22290

Closed drwwoob closed 1 month ago

drwwoob commented 2 months ago

Hello, I’m using emscripten to compile c++ code into js code. Our environment is node v14, and we are trying to come up with commonjs code. These are the tags I came up with, written in CMake

 SUFFIX ".js"
    LINK_FLAGS " \
    --bind                          \
    -s MODULARIZE=1                 \
    -s ASSERTIONS=2                 \
    -s MIN_NODE_VERSION=141703      \
    -o project.js                \
    -03                             \
    -lpthread"                                 

which when I call Module from the generated .js file, will give me this error

if (typeof __filename != 'undefined') _scriptName ||= __filename;
                                                    ^^^
SyntaxError: Unexpected token '||='

I figured this is an ES12 syntax, which node 14 does not fully support. But if I am to use -s EXPORT_ES6=1 I could not get a CommonJS code.

I found a solution that by changing

if (typeof __filename != 'undefined') _scriptName ||= __filename;

in the generated .js file into

if (typeof __filename != 'undefined') _scriptName = _scriptName || __filename;

then everything can compile.

I’m wondering if I have to change this every time generating the c++ project, or if there are other tags that could work this around.

Version of emscripten/emsdk: 3.1.61

brendandahl commented 2 months ago

I don't immediately see why it's not happening, but babel transpilation should remove that. You could try enabling debug with the environment variable EMCC_DEBUG=1 and seeing if babel is running.

drwwoob commented 2 months ago

i’ve enabled EMCC_DEBUG=1, and here’s part of the outcome

shared:DEBUG: successfully executed /Users/drwwoob/emsdk/node/18.20.3_64bit/bin/node /Users/drwwoob/emsdk/upstream/emscripten/node_modules/.bin/babel /var/folders/1t/bb241rj928n_d97qwc_7pp8h0000gp/T/emscripten_temp/robot_math.js -o /var/folders/1t/bb241rj928n_d97qwc_7pp8h0000gp/T/emscripten_temp/tmpqgzouygqbabel.js --presets @babel/preset-env --config-file /var/folders/1t/bb241rj928n_d97qwc_7pp8h0000gp/T/emscripten_temp/tmpr9kkz1fjbabel_config.json
profiler:DEBUG: block "transpile" took 0.609 seconds
profiler:DEBUG: block "transpile" took 0.609 seconds
building:DEBUG: saving debug copy /var/folders/1t/bb241rj928n_d97qwc_7pp8h0000gp/T/emscripten_temp/emcc-04-transpile.js
profiler:DEBUG: block "binaryen" took 0.609 seconds
link:DEBUG: Modularizing, assigning to var Module
building:DEBUG: saving debug copy /var/folders/1t/bb241rj928n_d97qwc_7pp8h0000gp/T/emscripten_temp/emcc-05-modularized.js
root:DEBUG: move: /var/folders/1t/bb241rj928n_d97qwc_7pp8h0000gp/T/emscripten_temp/tmpqgzouygqbabel.js.modular.js -> robot_math.js

where I do find emsdk/upstream/emscripten/node_modules/.bin/babel executed, but the ||= syntax still exist

brendandahl commented 2 months ago

Transpile is running in your case. I tested locally and see the same thing, but transpile is running before the modularize step, then the modularize step runs and adds that incompatible JS. We need to run transpile later, or emit more generic JS in the modularize step.

drwwoob commented 2 months ago

Any plan on that?

curiousdannii commented 2 months ago

Transpilation should def be a later step than modularising.

drwwoob commented 2 months ago

Transpilation should def be a later step than modularising.

so in link.py, i found the sequence of calling to be:

(at line 1875)

def phase_post_link(options, state, in_wasm, wasm_target, target, js_syms, base_metadata=None, linker_inputs=None):
  # … some other function calls here
  phase_binaryen(target, options, wasm_target)

  # If we are not emitting any JS then we are all done now
  if options.oformat != OFormat.WASM:
    phase_final_emitting(options, state, target, wasm_target)

where phase_binaryen calls transpile and phase_final_emitting calls modularize along with many other functions.

By looking at the code, I am thinking that moving the transpile section into phase_final_emitting would be the better option, but I don’t know if that is gonna mess other things up. Should I do a pull request on that and test it out?