First commit
diff --git a/emsdk.py b/emsdk.py index 8a314df..99f063f 100644 --- a/emsdk.py +++ b/emsdk.py
@@ -143,11 +143,7 @@ elif machine.endswith('86'): ARCH = 'x86' elif machine.startswith('aarch64') or machine.lower().startswith('arm64'): - if WINDOWS: - errlog('No support for Windows on Arm, fallback to x64') - ARCH = 'x86_64' - else: - ARCH = 'arm64' + ARCH = 'arm64' elif machine.startswith('arm'): ARCH = 'arm' else: @@ -2714,7 +2710,7 @@ errlog("Missing command; Type 'emsdk help' to get a list of commands.") return 1 - debug_print('esmdk.py running under `%s`' % sys.executable) + debug_print('emsdk.py running under `%s`' % sys.executable) cmd = args.pop(0) if cmd in ('help', '--help', '-h'):
diff --git a/emsdk_manifest.json b/emsdk_manifest.json index 61b3e2d..63a85bb 100644 --- a/emsdk_manifest.json +++ b/emsdk_manifest.json
@@ -396,6 +396,19 @@ { + "id": "node", + "version": "23.0.0", + "arch": "arm64", + "bitness": 64, + "windows_url": "node-v23.0.0-win-arm64.zip", + "activated_path": "%installation_dir%/bin", + "activated_path_skip": "node", + "activated_cfg": "NODE_JS='%installation_dir%/bin/node%.exe%'", + "activated_env": "EMSDK_NODE=%installation_dir%/bin/node%.exe%" + }, + + + { "id": "python", "version": "3.9.2-nuget", "bitness": 64, @@ -431,6 +444,17 @@ "activated_cfg": "PYTHON='%installation_dir%/bin/python3'", "activated_env": "EMSDK_PYTHON=%installation_dir%/bin/python3;SSL_CERT_FILE=%installation_dir%/lib/python3.9/site-packages/certifi/cacert.pem" }, + + { + "id": "python", + "version": "3.13.0", + "bitness": 64, + "arch": "arm64", + "windows_url": "python-3.13.0-0-arm64.zip", + "activated_cfg": "PYTHON='%installation_dir%/python.exe'", + "activated_env": "EMSDK_PYTHON=%installation_dir%/python.exe" + }, + { "id": "java", "version": "8.152", @@ -622,6 +646,14 @@ { "version": "main", "bitness": 64, + "arch": "arm64", + "uses": ["python-3.13.0-64bit", "llvm-git-main-64bit", "node-23.0.0-64bit", "emscripten-main-64bit", "binaryen-main-64bit"], + "os": "win" + }, + { + "version": "main", + "bitness": 64, + "arch": "amd64", "uses": ["python-3.9.2-nuget-64bit", "llvm-git-main-64bit", "node-18.20.3-64bit", "emscripten-main-64bit", "binaryen-main-64bit"], "os": "win" },
diff --git a/scripts/update_python.py b/scripts/update_python.py index a5848ea..432bf0b 100755 --- a/scripts/update_python.py +++ b/scripts/update_python.py
@@ -10,10 +10,10 @@ We only supply binaries for windows and macOS, but we do it very different ways for those two OSes. Windows recipe: - 1. Download the "embeddable zip file" version of python from python.org - 2. Remove .pth file to work around https://bugs.python.org/issue34841 - 3. Download and install pywin32 in the `site-packages` directory - 4. Re-zip and upload to storage.google.com + 1. Download precompiled version of python from NuGet package manager, + either the package "python" for AMD64, or "pythonarm64" for ARM64. + 2. Set up pip and install pywin32 and psutil via pip for emrun to work. + 3. Re-zip and upload to storage.google.com macOS recipe: 1. Clone cpython @@ -31,13 +31,13 @@ import sys from subprocess import check_call -version = '3.9.2' +version = '3.13.0' major_minor_version = '.'.join(version.split('.')[:2]) # e.g. '3.9.2' -> '3.9' -download_url = 'https://www.nuget.org/api/v2/package/python/%s' % version -revision = '4' +# This is not part of official Python version, but a repackaging number appended by emsdk +# when a version of Python needs to be redownloaded. +revision = '0' -pywin32_version = '227' -pywin32_base = 'https://github.com/mhammond/pywin32/releases/download/b%s/' % pywin32_version +PSUTIL = 'psutil==6.0.0' upload_base = 'gs://webassembly/emscripten-releases-builds/deps/' @@ -60,36 +60,45 @@ return ['zip', '-rq'] +# Detects whether current python interpreter architecture is ARM64 or AMD64 +# If running AMD64 python on an ARM64 Windows, this still intentionally returns AMD64 +def find_python_arch(): + import sysconfig + arch = sysconfig.get_platform().lower() + if 'amd64' in arch: + return 'amd64' + if 'arm64' in arch: + return 'arm64' + raise f'Unknown Python sysconfig platform "{arch}" (neither AMD64 or ARM64)' + + def make_python_patch(): - pywin32_filename = 'pywin32-%s.win-amd64-py%s.exe' % (pywin32_version, major_minor_version) - filename = 'python-%s-amd64.zip' % (version) - out_filename = 'python-%s-%s-amd64+pywin32.zip' % (version, revision) - if not os.path.exists(pywin32_filename): - url = pywin32_base + pywin32_filename - print('Downloading pywin32: ' + url) - urllib.request.urlretrieve(url, pywin32_filename) + python_arch = find_python_arch() + package_name = 'pythonarm64' if python_arch == 'arm64' else 'python' + download_url = f'https://www.nuget.org/api/v2/package/{package_name}/{version}' + filename = f'python-{version}-{python_arch}.zip' + out_filename = f'python-{version}-{revision}-{python_arch}.zip' if not os.path.exists(filename): - print('Downloading python: ' + download_url) + print(f'Downloading python: {download_url} to {filename}') urllib.request.urlretrieve(download_url, filename) os.mkdir('python-nuget') check_call(unzip_cmd() + [os.path.abspath(filename)], cwd='python-nuget') + os.remove(filename) - os.mkdir('pywin32') - rtn = subprocess.call(unzip_cmd() + [os.path.abspath(pywin32_filename)], cwd='pywin32') - assert rtn in [0, 1] + src_dir = os.path.join('python-nuget', 'tools') + python_exe = os.path.join(src_dir, 'python.exe') + check_call([python_exe, '-m', 'ensurepip', '--upgrade']) + check_call([python_exe, '-m', 'pip', 'install', 'pywin32==308']) + check_call([python_exe, '-m', 'pip', 'install', PSUTIL]) - os.mkdir(os.path.join('python-nuget', 'lib')) - shutil.move(os.path.join('pywin32', 'PLATLIB'), os.path.join('python-nuget', 'toolss', 'Lib', 'site-packages')) - - check_call(zip_cmd() + [os.path.join('..', '..', out_filename), '.'], cwd='python-nuget/tools') + check_call(zip_cmd() + [os.path.join('..', '..', out_filename), '.'], cwd=src_dir) + print('Created: %s' % out_filename) # cleanup if everything went fine shutil.rmtree('python-nuget') - shutil.rmtree('pywin32') - print('Created: %s' % out_filename) if '--upload' in sys.argv: upload_url = upload_base + out_filename print('Uploading: ' + upload_url) @@ -153,11 +162,15 @@ pybin = os.path.join(src_dir, 'install', 'usr', 'local', 'bin', 'python3') pip = os.path.join(src_dir, 'install', 'usr', 'local', 'bin', 'pip3') check_call([pybin, '-m', 'ensurepip', '--upgrade']) + # TODO: Potential bug: the following cmdline does not pin down a version + # of requests module, resulting in possibly different version of the module + # being installed on future runs. Switch to pip install requests==<version> to + # to download a pinned version. check_call([pybin, pip, 'install', 'requests']) # Install psutil module. This is needed by emrun to track when browser # process quits. - check_call([pybin, pip, 'install', 'psutil']) + check_call([pybin, pip, 'install', PSUTIL]) dirname = 'python-%s-%s' % (version, revision) if os.path.isdir(dirname):