From 659130e0ea408c517c43b7d45b3119aeccc033b0 Mon Sep 17 00:00:00 2001 From: Hood Chatham Date: Fri, 4 Oct 2024 14:01:11 +0200 Subject: [PATCH] gh-126898 Switch to exporting an es6 module and using a node_entry script --- Tools/wasm/emscripten/__main__.py | 36 +++++++++++++++++++--------- Tools/wasm/emscripten/node_entry.mjs | 30 +++++++++++++++++++++++ Tools/wasm/emscripten/node_pre.js | 15 ------------ configure | 4 ++-- configure.ac | 4 ++-- 5 files changed, 59 insertions(+), 30 deletions(-) create mode 100644 Tools/wasm/emscripten/node_entry.mjs delete mode 100644 Tools/wasm/emscripten/node_pre.js diff --git a/Tools/wasm/emscripten/__main__.py b/Tools/wasm/emscripten/__main__.py index 2015a3764ea8c8..9ce8dd6a364ad6 100644 --- a/Tools/wasm/emscripten/__main__.py +++ b/Tools/wasm/emscripten/__main__.py @@ -4,20 +4,22 @@ import contextlib import functools import os - -try: - from os import process_cpu_count as cpu_count -except ImportError: - from os import cpu_count -from pathlib import Path import shutil import subprocess import sys import sysconfig import tempfile +from pathlib import Path +from textwrap import dedent + +try: + from os import process_cpu_count as cpu_count +except ImportError: + from os import cpu_count -WASM_DIR = Path(__file__).parent.parent -CHECKOUT = WASM_DIR.parent.parent + +EMSCRIPTEN_DIR = Path(__file__).parent +CHECKOUT = EMSCRIPTEN_DIR.parent.parent.parent CROSS_BUILD_DIR = CHECKOUT / "cross-build" BUILD_DIR = CROSS_BUILD_DIR / "build" @@ -72,7 +74,7 @@ def wrapper(context): print("⎯" * terminal_width) print("📁", working_dir) if clean_ok and getattr(context, "clean", False) and working_dir.exists(): - print(f"🚮 Deleting directory (--clean)...") + print("🚮 Deleting directory (--clean)...") shutil.rmtree(working_dir) working_dir.mkdir(parents=True, exist_ok=True) @@ -207,9 +209,21 @@ def configure_emscripten_python(context, working_dir): quiet=context.quiet, ) - python_js = working_dir / "python.js" + shutil.copy(EMSCRIPTEN_DIR / "node_entry.mjs", working_dir / "node_entry.mjs") + + node_entry = working_dir / "node_entry.mjs" exec_script = working_dir / "python.sh" - exec_script.write_text(f'#!/bin/sh\nexec {host_runner} {python_js} "$@"\n') + exec_script.write_text( + dedent( + f"""\ + #!/bin/sh + + # We compute our own path, not following symlinks and pass it in so that + # node_entry.mjs can set sys.executable correctly. + exec {host_runner} {node_entry} "$(realpath -s $0)" "$@" + """ + ) + ) exec_script.chmod(0o755) print(f"🏃‍♀️ Created {exec_script} ... ") sys.stdout.flush() diff --git a/Tools/wasm/emscripten/node_entry.mjs b/Tools/wasm/emscripten/node_entry.mjs new file mode 100644 index 00000000000000..cb1c6ff3cba6aa --- /dev/null +++ b/Tools/wasm/emscripten/node_entry.mjs @@ -0,0 +1,30 @@ +import EmscriptenModule from "./python.mjs"; +import { dirname } from 'node:path'; +import { fileURLToPath } from 'node:url'; + +if (process?.versions?.node) { + const nodeVersion = Number(process.versions.node.split(".", 1)[0]); + if (nodeVersion < 18) { + process.stderr.write( + `Node version must be >= 18, got version ${process.version}\n`, + ); + process.exit(1); + } +} + +const settings = { + preRun(Module) { + const __dirname = dirname(fileURLToPath(import.meta.url)); + Module.FS.mkdirTree("/lib/"); + Module.FS.mount(Module.FS.filesystems.NODEFS, { root: __dirname + "/lib/" }, "/lib/"); + }, + // The first three arguments are: "node", path to this file, path to + // python.sh. After that come the arguments the user passed to python.sh. + arguments: process.argv.slice(3), + // Ensure that sys.executable, sys._base_executable, etc point to python.sh + // not to this file. To properly handle symlinks, python.sh needs to compute + // its own path. + thisProgram: process.argv[2], +}; + +await EmscriptenModule(settings); diff --git a/Tools/wasm/emscripten/node_pre.js b/Tools/wasm/emscripten/node_pre.js deleted file mode 100644 index 54b09dc08233f3..00000000000000 --- a/Tools/wasm/emscripten/node_pre.js +++ /dev/null @@ -1,15 +0,0 @@ -// If process is undefined, we're not running in the node runtime let it go I -// guess? -if (typeof process !== "undefined") { - const nodeVersion = Number(process.versions.node.split(".", 1)[0]); - if (nodeVersion < 18) { - process.stderr.write( - `Node version must be >= 18, got version ${process.version}\n`, - ); - process.exit(1); - } - Module.preRun = () => { - FS.mkdirTree("/lib/"); - FS.mount(NODEFS, { root: __dirname + "/lib/" }, "/lib/"); - }; -} diff --git a/configure b/configure index 5b44a3d69929a0..84b74ac3584bcd 100755 --- a/configure +++ b/configure @@ -7291,7 +7291,7 @@ else $as_nop case $ac_sys_system in #( Emscripten) : - EXEEXT=.js ;; #( + EXEEXT=.mjs ;; #( WASI) : EXEEXT=.wasm ;; #( *) : @@ -9432,6 +9432,7 @@ fi as_fn_append LDFLAGS_NODIST " -sWASM_BIGINT" as_fn_append LDFLAGS_NODIST " -sFORCE_FILESYSTEM -lidbfs.js -lnodefs.js -lproxyfs.js -lworkerfs.js" + as_fn_append LDFLAGS_NODIST " -sEXPORTED_RUNTIME_METHODS=FS" if test "x$enable_wasm_dynamic_linking" = xyes then : @@ -9450,7 +9451,6 @@ then : fi as_fn_append LDFLAGS_NODIST " -sALLOW_MEMORY_GROWTH" as_fn_append LDFLAGS_NODIST " -sEXIT_RUNTIME" - as_fn_append LDFLAGS_NODIST " --pre-js=\$(srcdir)/Tools/wasm/emscripten/node_pre.js" WASM_LINKFORSHARED_DEBUG="-gseparate-dwarf --emit-symbol-map" if test "x$wasm_debug" = xyes diff --git a/configure.ac b/configure.ac index 7904f8990c48ee..8fa6cb60900ad1 100644 --- a/configure.ac +++ b/configure.ac @@ -1327,7 +1327,7 @@ AC_ARG_WITH([suffix], ) ], [ AS_CASE([$ac_sys_system], - [Emscripten], [EXEEXT=.js], + [Emscripten], [EXEEXT=.mjs], [WASI], [EXEEXT=.wasm], [EXEEXT=] ) @@ -2328,6 +2328,7 @@ AS_CASE([$ac_sys_system], dnl Include file system support AS_VAR_APPEND([LDFLAGS_NODIST], [" -sFORCE_FILESYSTEM -lidbfs.js -lnodefs.js -lproxyfs.js -lworkerfs.js"]) + AS_VAR_APPEND([LDFLAGS_NODIST], [" -sEXPORTED_RUNTIME_METHODS=FS"]) AS_VAR_IF([enable_wasm_dynamic_linking], [yes], [ AS_VAR_APPEND([LINKFORSHARED], [" -sMAIN_MODULE"]) @@ -2341,7 +2342,6 @@ AS_CASE([$ac_sys_system], AS_VAR_APPEND([LDFLAGS_NODIST], [" -sALLOW_MEMORY_GROWTH"]) dnl not completely sure whether or not we want -sEXIT_RUNTIME, keeping it for now. AS_VAR_APPEND([LDFLAGS_NODIST], [" -sEXIT_RUNTIME"]) - AS_VAR_APPEND([LDFLAGS_NODIST], [" --pre-js=\$(srcdir)/Tools/wasm/emscripten/node_pre.js"]) WASM_LINKFORSHARED_DEBUG="-gseparate-dwarf --emit-symbol-map" AS_VAR_IF([wasm_debug], [yes], [