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]