Skip to content

Commit f9865f1

Browse files
committed
Parse Emscripten config and check version
1 parent 122113e commit f9865f1

File tree

3 files changed

+54
-15
lines changed

3 files changed

+54
-15
lines changed

Tools/wasm/wasm_build.py

Lines changed: 51 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,8 @@
88
Primary build targets are "emscripten-node-dl" (NodeJS, dynamic linking),
99
"emscripten-browser", and "wasi".
1010
11-
Emscripten builds require Emscripten SDK. The tools looks for 'EMSCRIPTEN'
12-
env var and falls back to EMSDK installed at /opt/emsdk.
11+
Emscripten builds require a recent Emscripten SDK. The tools looks for an
12+
activated EMSDK environment (". /path/to/emsdk_env.sh").
1313
1414
WASI builds require WASI SDK and wasmtime. The tool looks for 'WASI_SDK_PATH'
1515
and falls back to /opt/wasi-sdk.
@@ -35,18 +35,20 @@
3535

3636
# path to WASI-SDK root
3737
WASI_SDK_PATH = pathlib.Path(os.environ.get("WASI_SDK_PATH", "/opt/wasi-sdk"))
38-
# path to Emscripten directory (upstream/emscripten subdirectory in the EMSDK)
39-
EMSCRIPTEN_PATH = pathlib.Path(os.environ.get("EMSCRIPTEN", "/opt/emsdk/upstream/emscripten"))
38+
39+
# path to Emscripten SDK config file.
40+
# auto-detect's EMSDK in /opt/emsdk without ". emsdk_env.sh".
41+
EM_CONFIG = pathlib.Path(os.environ.setdefault("EM_CONFIG", "/opt/emsdk/.emscripten"))
42+
# 3.1.16 has broken utime()
43+
EMSDK_MIN_VERSION = (3, 1, 17)
44+
_MISSING = pathlib.PurePath("MISSING")
4045

4146
# WASM_WEBSERVER = WASMTOOLS / "wasmwebserver.py"
4247

4348
INSTALL_EMSDK = """
4449
wasm32-emscripten builds need Emscripten SDK. Please follow instructions at
4550
https://emscripten.org/docs/getting_started/downloads.html how to install
46-
Emscripten tp "/opt/emsdk". Alternatively you can install the SDK in a
47-
different location and set the environment variable
48-
EMSCRIPTEN=.../upstream/emscripten (the directory with emcc and
49-
emconfigure scripts), e.g. with ". emsdk_env.sh".
51+
Emscripten and how to activate the SDK with ". /path/to/emsdk_env.sh".
5052
"""
5153

5254
INSTALL_WASI_SDK = """
@@ -63,6 +65,26 @@
6365
"""
6466

6567

68+
def get_emscripten_root(emconfig: pathlib.Path = EM_CONFIG) -> pathlib.Path:
69+
"""Parse EM_CONFIG file and lookup EMSCRIPTEN_ROOT
70+
71+
The ".emscripten" config file is a Python snippet that uses "EM_CONFIG"
72+
environment variable. EMSCRIPTEN_ROOT is the "upstream/emscripten"
73+
subdirectory with tools like "emconfigure".
74+
"""
75+
if not emconfig.exists():
76+
return _MISSING
77+
with open(emconfig, encoding="utf-8") as f:
78+
code = f.read()
79+
# EM_CONFIG file is a Python snippet
80+
local = {}
81+
exec(code, globals(), local)
82+
return pathlib.Path(local["EMSCRIPTEN_ROOT"])
83+
84+
85+
EMSCRIPTEN_ROOT = get_emscripten_root()
86+
87+
6688
class MissingDependency(ValueError):
6789
def __init__(self, command: str, text: str):
6890
self.command = command
@@ -107,17 +129,34 @@ def getenv(self) -> dict:
107129

108130

109131
def _check_emscripten():
110-
emconfigure = EMSCRIPTEN_PATH / "emconfigure"
132+
if EMSCRIPTEN_ROOT is _MISSING:
133+
raise MissingDependency("Emscripten SDK EM_CONFIG", INSTALL_EMSDK)
134+
# sanity check
135+
emconfigure = EMSCRIPTEN.configure_wrapper
111136
if not emconfigure.exists():
112137
raise MissingDependency(emconfigure, INSTALL_EMSDK)
138+
# version check
139+
version_txt = EMSCRIPTEN_ROOT / "emscripten-version.txt"
140+
if not version_txt.exists():
141+
raise MissingDependency(version_txt, INSTALL_EMSDK)
142+
with open(version_txt) as f:
143+
version = f.read().strip().strip('"')
144+
version_tuple = tuple(int(v) for v in version.split("."))
145+
if version_tuple < EMSDK_MIN_VERSION:
146+
raise MissingDependency(
147+
version_txt,
148+
f"Emscripten SDK {version} in '{EMSCRIPTEN_ROOT}' is older than "
149+
"minimum required version "
150+
f"{'.'.join(str(v) for v in EMSDK_MIN_VERSION)}.",
151+
)
113152

114153

115154
EMSCRIPTEN = Platform(
116155
"emscripten",
117156
pythonexe="python.js",
118157
config_site=WASMTOOLS / "config.site-wasm32-emscripten",
119-
configure_wrapper=EMSCRIPTEN_PATH / "emconfigure",
120-
make_wrapper=EMSCRIPTEN_PATH / "emmake",
158+
configure_wrapper=EMSCRIPTEN_ROOT / "emconfigure",
159+
make_wrapper=EMSCRIPTEN_ROOT / "emmake",
121160
environ={"EM_COMPILER_WRAPPER": "ccache"} if HAS_CCACHE else None,
122161
check=_check_emscripten,
123162
)
@@ -434,7 +473,7 @@ def main():
434473
try:
435474
builder.host.platform.check()
436475
except MissingDependency as e:
437-
parser.exit(2, str(e))
476+
parser.exit(2, str(e) + "\n")
438477

439478
# hack for WASI
440479
if builder.host.is_wasi and not SETUP_LOCAL.exists():

configure

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

configure.ac

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1525,7 +1525,6 @@ if test "$cross_compiling" = yes; then
15251525
fi
15261526

15271527
AC_ARG_VAR([HOSTRUNNER], [Program to run CPython for the host platform])
1528-
AC_MSG_CHECKING([HOSTRUNNER])
15291528
if test -z "$HOSTRUNNER"
15301529
then
15311530
AS_CASE([$ac_sys_system/$ac_sys_emscripten_target],
@@ -1570,6 +1569,7 @@ then
15701569
)
15711570
fi
15721571
AC_SUBST([HOSTRUNNER])
1572+
AC_MSG_CHECKING([HOSTRUNNER])
15731573
AC_MSG_RESULT([$HOSTRUNNER])
15741574

15751575
if test -n "$HOSTRUNNER"; then

0 commit comments

Comments
 (0)