From 33a35ab65f6e4721ecdc846f08de0bd6980c26f5 Mon Sep 17 00:00:00 2001 From: Hood Chatham Date: Tue, 17 Mar 2026 10:46:23 +0100 Subject: [PATCH] gh-145805: Add `python Platforms/emscripten run` subcommand This should allow the build bot to be more agnostic to paths. I also added environment variables to set --quiet, --cross-build-dir, and --emsdk-cache --- Platforms/emscripten/__main__.py | 64 ++++++++++++++++++++++++-------- 1 file changed, 49 insertions(+), 15 deletions(-) diff --git a/Platforms/emscripten/__main__.py b/Platforms/emscripten/__main__.py index 7b5f6d2ab1bdd9..4dc13f05e9114c 100644 --- a/Platforms/emscripten/__main__.py +++ b/Platforms/emscripten/__main__.py @@ -77,9 +77,11 @@ def get_build_paths(cross_build_dir=None, emsdk_cache=None): LOCAL_SETUP_MARKER = b"# Generated by Platforms/wasm/emscripten.py\n" +@functools.cache def validate_emsdk_version(emsdk_cache): """Validate that the emsdk cache contains the required emscripten version.""" if emsdk_cache is None: + print("Build will use EMSDK from current environment.") return required_version = required_emscripten_version() emsdk_env = emsdk_activate_path(emsdk_cache) @@ -530,7 +532,6 @@ def configure_emscripten_python(context, working_dir): @subdir("host_dir") def make_emscripten_python(context, working_dir): """Run `make` for the emscripten/host build.""" - validate_emsdk_version(context.emsdk_cache) call( ["make", "--jobs", str(cpu_count()), "all"], env=updated_env({}, context.emsdk_cache), @@ -541,6 +542,22 @@ def make_emscripten_python(context, working_dir): subprocess.check_call([exec_script, "--version"]) +def run_emscripten_python(context): + """Run the built emscripten Python.""" + host_dir = context.build_paths["host_dir"] + exec_script = host_dir / "python.sh" + if not exec_script.is_file(): + print("Emscripten not built", file=sys.stderr) + sys.exit(1) + + args = context.args + # Strip the "--" separator if present + if args and args[0] == "--": + args = args[1:] + + os.execv(str(exec_script), [str(exec_script)] + args) + + def build_target(context): """Build one or more targets.""" steps = [] @@ -581,6 +598,18 @@ def clean_contents(context): print(f"🧹 Deleting generated {LOCAL_SETUP} ...") +def add_cross_build_dir_option(subcommand): + subcommand.add_argument( + "--cross-build-dir", + action="store", + default=os.environ.get("CROSS_BUILD_DIR"), + dest="cross_build_dir", + help="Path to the cross-build directory " + f"(default: {DEFAULT_CROSS_BUILD_DIR}). " + "Can also be set with the CROSS_BUILD_DIR environment variable.", + ) + + def main(): default_host_runner = "node" @@ -623,6 +652,17 @@ def main(): make_host = subcommands.add_parser( "make-host", help="Run `make` for the host/emscripten" ) + run = subcommands.add_parser( + "run", + help="Run the built emscripten Python", + ) + run.add_argument( + "args", + nargs=argparse.REMAINDER, + help="Arguments to pass to the emscripten Python " + "(use '--' to separate from run options)", + ) + add_cross_build_dir_option(run) clean = subcommands.add_parser( "clean", help="Delete files and directories created by this script" ) @@ -651,25 +691,20 @@ def main(): subcommand.add_argument( "--quiet", action="store_true", - default=False, + default="QUIET" in os.environ, dest="quiet", - help="Redirect output from subprocesses to a log file", - ) - subcommand.add_argument( - "--cross-build-dir", - action="store", - default=None, - dest="cross_build_dir", - help="Path to the cross-build directory " - f"(default: {DEFAULT_CROSS_BUILD_DIR})", + help="Redirect output from subprocesses to a log file. " + "Can also be set with the QUIET environment variable.", ) + add_cross_build_dir_option(subcommand) subcommand.add_argument( "--emsdk-cache", action="store", - default=None, + default=os.environ.get("EMSDK_CACHE"), dest="emsdk_cache", help="Path to emsdk cache directory. If provided, validates that " - "the required emscripten version is installed.", + "the required emscripten version is installed. " + "Can also be set with the EMSDK_CACHE environment variable.", ) for subcommand in configure_build, configure_host: subcommand.add_argument( @@ -699,8 +734,6 @@ def main(): if context.emsdk_cache: context.emsdk_cache = Path(context.emsdk_cache).absolute() - else: - print("Build will use EMSDK from current environment.") context.build_paths = get_build_paths( context.cross_build_dir, context.emsdk_cache @@ -715,6 +748,7 @@ def main(): "configure-host": configure_emscripten_python, "make-host": make_emscripten_python, "build": build_target, + "run": run_emscripten_python, "clean": clean_contents, }