https://github.com/python/cpython/commit/abd5246305655fc09e4e3c668c8ca09a1b0fc638
commit: abd5246305655fc09e4e3c668c8ca09a1b0fc638
branch: main
author: Hood Chatham <[email protected]>
committer: freakboy3742 <[email protected]>
date: 2026-03-19T09:06:17+08:00
summary:

gh-145805: Add `python Platforms/emscripten run` subcommand (#146051)

Provides a `run` command in the Emscripten build tooling, and adds 
environment variable configuration for EMSDK_CACHE, CROSS_BUILD_DIR
and QUIET.

files:
M Platforms/emscripten/__main__.py

diff --git a/Platforms/emscripten/__main__.py b/Platforms/emscripten/__main__.py
index 7b5f6d2ab1bdd9..78825a52fed29b 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"
 
 
[email protected]
 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,15 +598,31 @@ 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"
 
     parser = argparse.ArgumentParser()
     subcommands = parser.add_subparsers(dest="subcommand")
+
     install_emscripten_cmd = subcommands.add_parser(
         "install-emscripten",
         help="Install the appropriate version of Emscripten",
     )
+
     build = subcommands.add_parser("build", help="Build everything")
     build.add_argument(
         "target",
@@ -605,24 +638,46 @@ def main():
     configure_build = subcommands.add_parser(
         "configure-build-python", help="Run `configure` for the build Python"
     )
+
     make_mpdec_cmd = subcommands.add_parser(
         "make-mpdec",
         help="Clone mpdec repo, configure and build it for emscripten",
     )
+
     make_libffi_cmd = subcommands.add_parser(
         "make-libffi",
         help="Clone libffi repo, configure and build it for emscripten",
     )
+
     make_build = subcommands.add_parser(
         "make-build-python", help="Run `make` for the build Python"
     )
+
     configure_host = subcommands.add_parser(
         "configure-host",
-        help="Run `configure` for the host/emscripten (pydebug builds are 
inferred from the build Python)",
+        help=(
+            "Run `configure` for the host/emscripten "
+            "(pydebug builds are inferred from the build Python)"
+        ),
     )
+
     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,26 +706,26 @@ 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.",
+            help=(
+                "Path to emsdk cache directory. If provided, validates that "
+                "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(
             "--clean",
@@ -679,10 +734,12 @@ def main():
             dest="clean",
             help="Delete any relevant directories before building",
         )
+
     for subcommand in build, configure_build, configure_host:
         subcommand.add_argument(
             "args", nargs="*", help="Extra arguments to pass to `configure`"
         )
+
     for subcommand in build, configure_host:
         subcommand.add_argument(
             "--host-runner",
@@ -699,8 +756,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 +770,7 @@ def main():
         "configure-host": configure_emscripten_python,
         "make-host": make_emscripten_python,
         "build": build_target,
+        "run": run_emscripten_python,
         "clean": clean_contents,
     }
 

_______________________________________________
Python-checkins mailing list -- [email protected]
To unsubscribe send an email to [email protected]
https://mail.python.org/mailman3//lists/python-checkins.python.org
Member address: [email protected]

Reply via email to