https://github.com/python/cpython/commit/c3fb0d9d96902774c08b199dda0479a8d31398a5
commit: c3fb0d9d96902774c08b199dda0479a8d31398a5
branch: main
author: Hood Chatham <[email protected]>
committer: freakboy3742 <[email protected]>
date: 2026-03-06T08:42:41+08:00
summary:

gh-145177: Support multiple Emscripten versions for Emscripten buildbot 
(#145180)

Adds an `--emsdk-cache` argument to the Emscripten build script and an
emscripten_version.txt file. If the `--emsdk-cache` argument is passed, the 
build script
will look in `emscripten_version.txt` to get the expected emsdk version is 
installed in
a folder called e.g., 4.0.12 in the directory indicated by the `--emsdk-cache` 
argument,
and run the build with that Emscripten tooling activated.

files:
A Tools/wasm/emscripten/emscripten_version.txt
M Tools/wasm/emscripten/__main__.py

diff --git a/Tools/wasm/emscripten/__main__.py 
b/Tools/wasm/emscripten/__main__.py
index c88e9edba6d230..856a7f8252bb7c 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_FILE = EMSCRIPTEN_DIR / "emscripten_version.txt"
 
 CROSS_BUILD_DIR = CHECKOUT / "cross-build"
 NATIVE_BUILD_DIR = CROSS_BUILD_DIR / "build"
@@ -36,7 +37,56 @@
 LOCAL_SETUP_MARKER = b"# Generated by Tools/wasm/emscripten.py\n"
 
 
-def updated_env(updates={}):
[email protected]
+def get_required_emscripten_version():
+    """Read the required emscripten version from emscripten_version.txt."""
+    return EMSCRIPTEN_VERSION_FILE.read_text().strip()
+
+
[email protected]
+def get_emsdk_activate_path(emsdk_cache):
+    required_version = get_required_emscripten_version()
+    return Path(emsdk_cache) / required_version / "emsdk_env.sh"
+
+
+def validate_emsdk_version(emsdk_cache):
+    """Validate that the emsdk cache contains the required emscripten 
version."""
+    required_version = get_required_emscripten_version()
+    emsdk_env = get_emsdk_activate_path(emsdk_cache)
+    if not emsdk_env.is_file():
+        print(
+            f"Required emscripten version {required_version} not found in 
{emsdk_cache}",
+            file=sys.stderr,
+        )
+        sys.exit(1)
+    print(f"✅ Emscripten version {required_version} found in {emsdk_cache}")
+
+
+def parse_env(text):
+    result = {}
+    for line in text.splitlines():
+        key, val = line.split("=", 1)
+        result[key] = val
+    return result
+
+
[email protected]
+def get_emsdk_environ(emsdk_cache):
+    """Returns os.environ updated by sourcing emsdk_env.sh"""
+    if not emsdk_cache:
+        return os.environ
+    env_text = subprocess.check_output(
+        [
+            "bash",
+            "-c",
+            f"EMSDK_QUIET=1 source {get_emsdk_activate_path(emsdk_cache)} && 
env",
+        ],
+        text=True,
+    )
+    return parse_env(env_text)
+
+
+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.
@@ -52,8 +102,7 @@ def updated_env(updates={}):
     except subprocess.CalledProcessError:
         pass  # Might be building from a tarball.
     # This layering lets SOURCE_DATE_EPOCH from os.environ takes precedence.
-    environment = env_defaults | os.environ | updates
-
+    environment = env_defaults | get_emsdk_environ(emsdk_cache) | updates
     env_diff = {}
     for key, value in environment.items():
         if os.environ.get(key) != value:
@@ -204,7 +253,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 +280,7 @@ def make_mpdec(context, working_dir):
         ],
         cwd=mpdec_dir,
         quiet=context.quiet,
+        env=updated_env({}, context.emsdk_cache),
     )
     call(
         ["make", "install"],
@@ -300,7 +350,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 +408,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,
     )
 
@@ -439,6 +489,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 +521,12 @@ def main():
 
     context = parser.parse_args()
 
+    if context.emsdk_cache:
+        validate_emsdk_version(context.emsdk_cache)
+        context.emsdk_cache = Path(context.emsdk_cache).absolute()
+    else:
+        print("Build will use EMSDK from current environment.")
+
     dispatch = {
         "make-libffi": make_emscripten_libffi,
         "make-mpdec": make_mpdec,
diff --git a/Tools/wasm/emscripten/emscripten_version.txt 
b/Tools/wasm/emscripten/emscripten_version.txt
new file mode 100644
index 00000000000000..4c05e4ef57dbf8
--- /dev/null
+++ b/Tools/wasm/emscripten/emscripten_version.txt
@@ -0,0 +1 @@
+4.0.12

_______________________________________________
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