From 6087f491ea1e4c8c115bb02d95e391399c0d6fe7 Mon Sep 17 00:00:00 2001 From: Christian Heimes Date: Fri, 19 Aug 2022 08:36:12 +0200 Subject: [PATCH] gh-95853: WASM: better version and asset handling in scripts (GH-96045) - support EMSDK tot-upstream and git releases - allow WASM assents for wasm64-emscripten and WASI. This makes single file distributions on WASI easier. - decouple WASM assets from browser builds --- Makefile.pre.in | 5 +++-- Tools/wasm/wasm_assets.py | 14 +++++++++++++- Tools/wasm/wasm_build.py | 25 ++++++++++++++++++++++++- configure | 2 +- configure.ac | 2 +- 5 files changed, 42 insertions(+), 6 deletions(-) diff --git a/Makefile.pre.in b/Makefile.pre.in index ae7735cf69a..414e6045b4d 100644 --- a/Makefile.pre.in +++ b/Makefile.pre.in @@ -803,10 +803,11 @@ $(DLLLIBRARY) libpython$(LDVERSION).dll.a: $(LIBRARY_OBJS) # wasm assets directory is relative to current build dir, e.g. "./usr/local". # --preload-file turns a relative asset path into an absolute path. +.PHONY: wasm_stdlib +wasm_stdlib: $(WASM_STDLIB) $(WASM_STDLIB): $(srcdir)/Lib/*.py $(srcdir)/Lib/*/*.py \ $(srcdir)/Tools/wasm/wasm_assets.py \ - Makefile pybuilddir.txt Modules/Setup.local \ - python.html python.worker.js + Makefile pybuilddir.txt Modules/Setup.local $(PYTHON_FOR_BUILD) $(srcdir)/Tools/wasm/wasm_assets.py \ --buildroot . --prefix $(prefix) diff --git a/Tools/wasm/wasm_assets.py b/Tools/wasm/wasm_assets.py index 695e6ffc31f..a300d594414 100755 --- a/Tools/wasm/wasm_assets.py +++ b/Tools/wasm/wasm_assets.py @@ -108,6 +108,14 @@ "_zoneinfo": ["zoneinfo/"], } +SYSCONFIG_NAMES = ( + "_sysconfigdata__emscripten_wasm32-emscripten", + "_sysconfigdata__emscripten_wasm32-emscripten", + "_sysconfigdata__wasi_wasm32-wasi", + "_sysconfigdata__wasi_wasm64-wasi", +) + + def get_builddir(args: argparse.Namespace) -> pathlib.Path: """Get builddir path from pybuilddir.txt """ @@ -120,7 +128,11 @@ def get_sysconfigdata(args: argparse.Namespace) -> pathlib.Path: """Get path to sysconfigdata relative to build root """ data_name = sysconfig._get_sysconfigdata_name() - assert "emscripten_wasm32" in data_name + if not data_name.startswith(SYSCONFIG_NAMES): + raise ValueError( + f"Invalid sysconfig data name '{data_name}'.", + SYSCONFIG_NAMES + ) filename = data_name + ".py" return args.builddir / filename diff --git a/Tools/wasm/wasm_build.py b/Tools/wasm/wasm_build.py index df90f01a27b..5ccf88cbc44 100755 --- a/Tools/wasm/wasm_build.py +++ b/Tools/wasm/wasm_build.py @@ -20,6 +20,7 @@ import dataclasses import os import pathlib +import re import shlex import shutil import subprocess @@ -99,6 +100,24 @@ def get_emscripten_root(emconfig: pathlib.Path = EM_CONFIG) -> pathlib.PurePath: EMSCRIPTEN_ROOT = get_emscripten_root() +def read_python_version(configure: pathlib.Path = CONFIGURE) -> str: + """Read PACKAGE_VERSION from configure script + + configure and configure.ac are the canonical source for major and + minor version number. + """ + version_re = re.compile("^PACKAGE_VERSION='(\d\.\d+)'") + with configure.open(encoding="utf-8") as f: + for line in f: + mo = version_re.match(line) + if mo: + return mo.group(1) + raise ValueError(f"PACKAGE_VERSION not found in {configure}") + + +PYTHON_VERSION = read_python_version() + + class ConditionError(ValueError): def __init__(self, info: str, text: str): self.info = info @@ -174,6 +193,9 @@ def _check_emscripten(): raise MissingDependency(os.fspath(version_txt), INSTALL_EMSDK) with open(version_txt) as f: version = f.read().strip().strip('"') + if version.endswith("-git"): + # git / upstream / tot-upstream installation + version = version[:-4] version_tuple = tuple(int(v) for v in version.split(".")) if version_tuple < EMSDK_MIN_VERSION: raise MissingDependency( @@ -221,7 +243,7 @@ def _check_wasi(): # workaround for https://github.com/python/cpython/issues/95952 "HOSTRUNNER": ( "wasmtime run " - "--env PYTHONPATH=/{relbuilddir}/build/lib.wasi-wasm32-$(VERSION):/Lib " + "--env PYTHONPATH=/{relbuilddir}/build/lib.wasi-wasm32-{version}:/Lib " "--mapdir /::{srcdir} --" ), }, @@ -362,6 +384,7 @@ def getenv(self) -> dict: env[key] = value.format( relbuilddir=self.builddir.relative_to(SRCDIR), srcdir=SRCDIR, + version=PYTHON_VERSION, ) else: env[key] = value diff --git a/configure b/configure index fb3a3c3fc8f..1801f806ae1 100755 --- a/configure +++ b/configure @@ -7038,7 +7038,7 @@ $as_echo "$LDLIBRARY" >&6; } # LIBRARY_DEPS, LINK_PYTHON_OBJS and LINK_PYTHON_DEPS variable case $ac_sys_system/$ac_sys_emscripten_target in #( Emscripten/browser*) : - LIBRARY_DEPS='$(PY3LIBRARY) $(WASM_STDLIB)' ;; #( + LIBRARY_DEPS='$(PY3LIBRARY) $(WASM_STDLIB) python.html python.worker.js' ;; #( *) : LIBRARY_DEPS='$(PY3LIBRARY) $(EXPORTSYMS)' ;; diff --git a/configure.ac b/configure.ac index bab405e6ed3..bb9fec07242 100644 --- a/configure.ac +++ b/configure.ac @@ -1581,7 +1581,7 @@ AC_MSG_RESULT($LDLIBRARY) # LIBRARY_DEPS, LINK_PYTHON_OBJS and LINK_PYTHON_DEPS variable AS_CASE([$ac_sys_system/$ac_sys_emscripten_target], - [Emscripten/browser*], [LIBRARY_DEPS='$(PY3LIBRARY) $(WASM_STDLIB)'], + [Emscripten/browser*], [LIBRARY_DEPS='$(PY3LIBRARY) $(WASM_STDLIB) python.html python.worker.js'], [LIBRARY_DEPS='$(PY3LIBRARY) $(EXPORTSYMS)'] ) LINK_PYTHON_DEPS='$(LIBRARY_DEPS)'