Skip to content

Commit c3fb0d9

Browse files
authored
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.
1 parent 7232883 commit c3fb0d9

File tree

2 files changed

+71
-6
lines changed

2 files changed

+71
-6
lines changed

Tools/wasm/emscripten/__main__.py

Lines changed: 70 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222

2323
EMSCRIPTEN_DIR = Path(__file__).parent
2424
CHECKOUT = EMSCRIPTEN_DIR.parent.parent.parent
25+
EMSCRIPTEN_VERSION_FILE = EMSCRIPTEN_DIR / "emscripten_version.txt"
2526

2627
CROSS_BUILD_DIR = CHECKOUT / "cross-build"
2728
NATIVE_BUILD_DIR = CROSS_BUILD_DIR / "build"
@@ -36,7 +37,56 @@
3637
LOCAL_SETUP_MARKER = b"# Generated by Tools/wasm/emscripten.py\n"
3738

3839

39-
def updated_env(updates={}):
40+
@functools.cache
41+
def get_required_emscripten_version():
42+
"""Read the required emscripten version from emscripten_version.txt."""
43+
return EMSCRIPTEN_VERSION_FILE.read_text().strip()
44+
45+
46+
@functools.cache
47+
def get_emsdk_activate_path(emsdk_cache):
48+
required_version = get_required_emscripten_version()
49+
return Path(emsdk_cache) / required_version / "emsdk_env.sh"
50+
51+
52+
def validate_emsdk_version(emsdk_cache):
53+
"""Validate that the emsdk cache contains the required emscripten version."""
54+
required_version = get_required_emscripten_version()
55+
emsdk_env = get_emsdk_activate_path(emsdk_cache)
56+
if not emsdk_env.is_file():
57+
print(
58+
f"Required emscripten version {required_version} not found in {emsdk_cache}",
59+
file=sys.stderr,
60+
)
61+
sys.exit(1)
62+
print(f"✅ Emscripten version {required_version} found in {emsdk_cache}")
63+
64+
65+
def parse_env(text):
66+
result = {}
67+
for line in text.splitlines():
68+
key, val = line.split("=", 1)
69+
result[key] = val
70+
return result
71+
72+
73+
@functools.cache
74+
def get_emsdk_environ(emsdk_cache):
75+
"""Returns os.environ updated by sourcing emsdk_env.sh"""
76+
if not emsdk_cache:
77+
return os.environ
78+
env_text = subprocess.check_output(
79+
[
80+
"bash",
81+
"-c",
82+
f"EMSDK_QUIET=1 source {get_emsdk_activate_path(emsdk_cache)} && env",
83+
],
84+
text=True,
85+
)
86+
return parse_env(env_text)
87+
88+
89+
def updated_env(updates, emsdk_cache):
4090
"""Create a new dict representing the environment to use.
4191
4292
The changes made to the execution environment are printed out.
@@ -52,8 +102,7 @@ def updated_env(updates={}):
52102
except subprocess.CalledProcessError:
53103
pass # Might be building from a tarball.
54104
# This layering lets SOURCE_DATE_EPOCH from os.environ takes precedence.
55-
environment = env_defaults | os.environ | updates
56-
105+
environment = env_defaults | get_emsdk_environ(emsdk_cache) | updates
57106
env_diff = {}
58107
for key, value in environment.items():
59108
if os.environ.get(key) != value:
@@ -204,7 +253,7 @@ def make_emscripten_libffi(context, working_dir):
204253
)
205254
call(
206255
[EMSCRIPTEN_DIR / "make_libffi.sh"],
207-
env=updated_env({"PREFIX": PREFIX_DIR}),
256+
env=updated_env({"PREFIX": PREFIX_DIR}, context.emsdk_cache),
208257
cwd=libffi_dir,
209258
quiet=context.quiet,
210259
)
@@ -231,6 +280,7 @@ def make_mpdec(context, working_dir):
231280
],
232281
cwd=mpdec_dir,
233282
quiet=context.quiet,
283+
env=updated_env({}, context.emsdk_cache),
234284
)
235285
call(
236286
["make", "install"],
@@ -300,7 +350,7 @@ def configure_emscripten_python(context, working_dir):
300350
configure.extend(context.args)
301351
call(
302352
configure,
303-
env=updated_env(env_additions),
353+
env=updated_env(env_additions, context.emsdk_cache),
304354
quiet=context.quiet,
305355
)
306356

@@ -358,7 +408,7 @@ def make_emscripten_python(context, working_dir):
358408
"""Run `make` for the emscripten/host build."""
359409
call(
360410
["make", "--jobs", str(cpu_count()), "all"],
361-
env=updated_env(),
411+
env=updated_env({}, context.emsdk_cache),
362412
quiet=context.quiet,
363413
)
364414

@@ -439,6 +489,14 @@ def main():
439489
dest="quiet",
440490
help="Redirect output from subprocesses to a log file",
441491
)
492+
subcommand.add_argument(
493+
"--emsdk-cache",
494+
action="store",
495+
default=None,
496+
dest="emsdk_cache",
497+
help="Path to emsdk cache directory. If provided, validates that "
498+
"the required emscripten version is installed.",
499+
)
442500
for subcommand in configure_build, configure_host:
443501
subcommand.add_argument(
444502
"--clean",
@@ -463,6 +521,12 @@ def main():
463521

464522
context = parser.parse_args()
465523

524+
if context.emsdk_cache:
525+
validate_emsdk_version(context.emsdk_cache)
526+
context.emsdk_cache = Path(context.emsdk_cache).absolute()
527+
else:
528+
print("Build will use EMSDK from current environment.")
529+
466530
dispatch = {
467531
"make-libffi": make_emscripten_libffi,
468532
"make-mpdec": make_mpdec,
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
4.0.12

0 commit comments

Comments
 (0)