Skip to content

Commit

Permalink
Update Python to 3.13.0 and add support to Windows on AMD64. Rewrite …
Browse files Browse the repository at this point in the history
…packaging of pywin32 because it is no longer shipped via separate binary installers, but has migrated to use pip.
  • Loading branch information
juj committed Oct 18, 2024
1 parent 5e398ab commit eacc02c
Show file tree
Hide file tree
Showing 7 changed files with 83 additions and 33 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ https://emscripten.org/docs/building_from_source/toolchain_what_is_needed.html.

### Linux

- `python`: Version 3.9.2 or above.
- `python`: Version 3.13.0 or above.
- `java`: For running closure compiler (optional)

The emsdk pre-compiled binaries are built against Ubuntu/Focal 20.04 LTS and
Expand Down
5 changes: 4 additions & 1 deletion emsdk
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,10 @@

# First look for python bundled in Emsdk
if [ -z "$EMSDK_PYTHON" ]; then
PYTHON3="$(dirname "$0")/python/3.9.2-1_64bit/bin/python3"
PYTHON3="$(dirname "$0")/python/3.13.0-0_64bit/bin/python3"
if [ ! -f "$PYTHON3" ]; then
PYTHON3="$(dirname "$0")/python/3.9.2-1_64bit/bin/python3"
fi
if [ -f "$PYTHON3" ]; then
EMSDK_PYTHON="$PYTHON3"

Expand Down
8 changes: 8 additions & 0 deletions emsdk.bat
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,14 @@ setlocal
:: When using our bundled python we never want the users
:: PYTHONHOME or PYTHONPATH
:: https://github.com/emscripten-core/emsdk/issues/598

if exist "%~dp0python\3.13.0-0_64bit\python.exe" (
set EMSDK_PY="%~dp0python\3.13.0-0_64bit\python.exe"
set PYTHONHOME=
set PYTHONPATH=
goto end
)

if exist "%~dp0python\3.9.2-1_64bit\python.exe" (
set EMSDK_PY="%~dp0python\3.9.2-1_64bit\python.exe"
set PYTHONHOME=
Expand Down
1 change: 1 addition & 0 deletions emsdk.ps1
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
$ScriptDirectory = Split-Path -parent $PSCommandPath

$PythonLocations = $(
"python\3.13.0-0_64bit\python.exe",
"python\3.9.2-1_64bit\python.exe",
"python\3.9.2-nuget_64bit\python.exe"
)
Expand Down
6 changes: 1 addition & 5 deletions emsdk.py
Original file line number Diff line number Diff line change
Expand Up @@ -143,11 +143,7 @@ def exit_with_error(msg):
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:
Expand Down
42 changes: 40 additions & 2 deletions emsdk_manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,44 @@
"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": "x86_64",
"windows_url": "python-3.13.0-0-win-amd64.zip",
"activated_cfg": "PYTHON='%installation_dir%/python.exe'",
"activated_env": "EMSDK_PYTHON=%installation_dir%/python.exe"
},
{
"id": "python",
"version": "3.13.0",
"bitness": 64,
"arch": "arm64",
"windows_url": "python-3.13.0-0-win-arm64.zip",
"activated_cfg": "PYTHON='%installation_dir%/python.exe'",
"activated_env": "EMSDK_PYTHON=%installation_dir%/python.exe"
},
{
"id": "python",
"version": "3.13.0",
"bitness": 64,
"arch": "x86_64",
"macos_url": "python-3.13.0-0-macos-x86_64.tar.gz",
"activated_cfg": "PYTHON='%installation_dir%/bin/python3'",
"activated_env": "EMSDK_PYTHON=%installation_dir%/bin/python3;SSL_CERT_FILE=%installation_dir%/lib/python3.13/site-packages/certifi/cacert.pem"
},
{
"id": "python",
"version": "3.13.0",
"bitness": 64,
"arch": "arm64",
"macos_url": "python-3.13.0-0-macos-arm64.tar.gz",
"activated_cfg": "PYTHON='%installation_dir%/bin/python3'",
"activated_env": "EMSDK_PYTHON=%installation_dir%/bin/python3;SSL_CERT_FILE=%installation_dir%/lib/python3.13/site-packages/certifi/cacert.pem"
},

{
"id": "java",
"version": "8.152",
Expand Down Expand Up @@ -368,13 +406,13 @@
{
"version": "main",
"bitness": 64,
"uses": ["python-3.9.2-nuget-64bit", "llvm-git-main-64bit", "node-20.18.0-64bit", "emscripten-main-64bit", "binaryen-main-64bit"],
"uses": ["python-3.13.0-64bit", "llvm-git-main-64bit", "node-20.18.0-64bit", "emscripten-main-64bit", "binaryen-main-64bit"],
"os": "win"
},
{
"version": "main",
"bitness": 64,
"uses": ["python-3.9.2-64bit", "llvm-git-main-64bit", "node-20.18.0-64bit", "emscripten-main-64bit", "binaryen-main-64bit"],
"uses": ["python-3.13.0-64bit", "llvm-git-main-64bit", "node-20.18.0-64bit", "emscripten-main-64bit", "binaryen-main-64bit"],
"os": "macos"
},
{
Expand Down
52 changes: 28 additions & 24 deletions scripts/update_python.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -32,29 +32,35 @@
from subprocess import check_call
from zip import unzip_cmd, zip_cmd

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
# 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 = '4'

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/'


# 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}-win-{python_arch}.zip'
out_filename = f'python-{version}-{revision}-{python_arch}.zip'

if not os.path.exists(filename):
print(f'Downloading python: {download_url} to {filename}')
Expand All @@ -64,19 +70,17 @@ def make_python_patch():
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')

if '--upload' in sys.argv:
upload_url = upload_base + out_filename
Expand Down Expand Up @@ -149,7 +153,7 @@ def build_python():

# 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):
Expand Down

0 comments on commit eacc02c

Please sign in to comment.