diff --git a/Tools/wasm/emscripten/__main__.py b/Tools/wasm/emscripten/__main__.py index c88e9edba6d230..e6f6aa7a6f90c0 100644 --- a/Tools/wasm/emscripten/__main__.py +++ b/Tools/wasm/emscripten/__main__.py @@ -22,6 +22,7 @@ EMSCRIPTEN_DIR = Path(__file__).parent CHECKOUT = EMSCRIPTEN_DIR.parent.parent.parent +EMSCRIPTEN_VERSION = "4.0.12" CROSS_BUILD_DIR = CHECKOUT / "cross-build" NATIVE_BUILD_DIR = CROSS_BUILD_DIR / "build" @@ -36,7 +37,24 @@ LOCAL_SETUP_MARKER = b"# Generated by Tools/wasm/emscripten.py\n" -def updated_env(updates={}): +@functools.cache +def get_emsdk_activate_path(emsdk_cache): + return Path(emsdk_cache) / EMSCRIPTEN_VERSION / "emsdk_env.sh" + + +def validate_emsdk_version(emsdk_cache): + """Validate that the emsdk cache contains the required emscripten version.""" + emsdk_env = get_emsdk_activate_path(emsdk_cache) + if not emsdk_env.is_file(): + print( + f"Required emscripten version {EMSCRIPTEN_VERSION} not found in {emsdk_cache}", + file=sys.stderr, + ) + sys.exit(1) + print(f"✅ Emscripten version {EMSCRIPTEN_VERSION} found in {emsdk_cache}") + + +def updated_env(updates, emsdk_cache): """Create a new dict representing the environment to use. The changes made to the execution environment are printed out. @@ -53,6 +71,15 @@ def updated_env(updates={}): pass # Might be building from a tarball. # This layering lets SOURCE_DATE_EPOCH from os.environ takes precedence. environment = env_defaults | os.environ | updates + if emsdk_cache: + env = os.environ.copy() + call( + ["bash", "-c", f"source {get_emsdk_activate_path(emsdk_cache)}"], + env=env, + quiet=False, + ) + for key in ["PATH", "EMSDK", "EMSDK_NODE"]: + environment[key] = env[key] env_diff = {} for key, value in environment.items(): @@ -204,7 +231,7 @@ def make_emscripten_libffi(context, working_dir): ) call( [EMSCRIPTEN_DIR / "make_libffi.sh"], - env=updated_env({"PREFIX": PREFIX_DIR}), + env=updated_env({"PREFIX": PREFIX_DIR}, context.emsdk_cache), cwd=libffi_dir, quiet=context.quiet, ) @@ -231,6 +258,7 @@ def make_mpdec(context, working_dir): ], cwd=mpdec_dir, quiet=context.quiet, + env=updated_env({}, context.emsdk_cache), ) call( ["make", "install"], @@ -300,7 +328,7 @@ def configure_emscripten_python(context, working_dir): configure.extend(context.args) call( configure, - env=updated_env(env_additions), + env=updated_env(env_additions, context.emsdk_cache), quiet=context.quiet, ) @@ -358,7 +386,7 @@ def make_emscripten_python(context, working_dir): """Run `make` for the emscripten/host build.""" call( ["make", "--jobs", str(cpu_count()), "all"], - env=updated_env(), + env=updated_env({}, context.emsdk_cache), quiet=context.quiet, ) @@ -392,6 +420,11 @@ def clean_contents(context): print(f"🧹 Deleting generated {LOCAL_SETUP} ...") +def print_emscripten_version(context): + """Print the required emscripten version.""" + print(EMSCRIPTEN_VERSION) + + def main(): default_host_runner = "node" @@ -422,6 +455,9 @@ def main(): clean = subcommands.add_parser( "clean", help="Delete files and directories created by this script" ) + emscripten_version_cmd = subcommands.add_parser( + "emscripten-version", help="Print the required emscripten version" + ) for subcommand in ( build, configure_build, @@ -431,6 +467,7 @@ def main(): configure_host, make_host, clean, + emscripten_version_cmd, ): subcommand.add_argument( "--quiet", @@ -439,6 +476,14 @@ def main(): dest="quiet", help="Redirect output from subprocesses to a log file", ) + subcommand.add_argument( + "--emsdk-cache", + action="store", + default=None, + dest="emsdk_cache", + help="Path to emsdk cache directory. If provided, validates that " + "the required emscripten version is installed.", + ) for subcommand in configure_build, configure_host: subcommand.add_argument( "--clean", @@ -463,6 +508,10 @@ def main(): context = parser.parse_args() + if context.emsdk_cache: + validate_emsdk_version(context.emsdk_cache) + context.emsdk_cache = Path(context.emsdk_cache).absolute() + dispatch = { "make-libffi": make_emscripten_libffi, "make-mpdec": make_mpdec, @@ -472,6 +521,7 @@ def main(): "make-host": make_emscripten_python, "build": build_all, "clean": clean_contents, + "emscripten-version": print_emscripten_version, } if not context.subcommand: