8
8
http://storage.google.com/webassembly.
9
9
10
10
We only supply binaries for windows and macOS, but we do it very different ways for those two OSes.
11
+ On Linux, we depend on the system version of python.
11
12
12
13
Windows recipe:
13
- 1. Download the "embeddable zip file" version of python from python.org
14
- 2. Remove .pth file to work around https://bugs.python.org/issue34841
15
- 3. Download and install pywin32 in the `site-packages` directory
16
- 4 . Re-zip and upload to storage.google.com
14
+ 1. Download precompiled version of python from NuGet package manager,
15
+ either the package "python" for AMD64, or "pythonarm64" for ARM64.
16
+ 2. Set up pip and install pywin32 and psutil via pip for emrun to work.
17
+ 3 . Re-zip and upload to storage.google.com
17
18
18
19
macOS recipe:
19
20
1. Clone cpython
32
33
from subprocess import check_call
33
34
from zip import unzip_cmd , zip_cmd
34
35
35
- version = '3.9.2 '
36
+ version = '3.13.3 '
36
37
major_minor_version = '.' .join (version .split ('.' )[:2 ]) # e.g. '3.9.2' -> '3.9'
37
- download_url = 'https://www.nuget.org/api/v2/package/python/%s' % version
38
38
# This is not part of official Python version, but a repackaging number appended by emsdk
39
39
# when a version of Python needs to be redownloaded.
40
- revision = '4 '
40
+ revision = '0 '
41
41
42
- pywin32_version = '227'
43
- pywin32_base = 'https://github.com/mhammond/pywin32/releases/download/b%s/' % pywin32_version
42
+ PSUTIL = 'psutil==7.0.0'
44
43
45
44
upload_base = 'gs://webassembly/emscripten-releases-builds/deps/'
46
45
47
46
47
+ # Detects whether current python interpreter architecture is ARM64 or AMD64
48
+ # If running AMD64 python on an ARM64 Windows, this still intentionally returns AMD64
49
+ def find_python_arch ():
50
+ import sysconfig
51
+ arch = sysconfig .get_platform ().lower ()
52
+ if 'amd64' in arch :
53
+ return 'amd64'
54
+ if 'arm64' in arch :
55
+ return 'arm64'
56
+ raise f'Unknown Python sysconfig platform "{ arch } " (neither AMD64 or ARM64)'
57
+
58
+
48
59
def make_python_patch ():
49
- pywin32_filename = 'pywin32-%s.win-amd64-py%s.exe' % (pywin32_version , major_minor_version )
50
- filename = 'python-%s-amd64.zip' % (version )
51
- out_filename = 'python-%s-%s-amd64+pywin32.zip' % (version , revision )
52
- if not os .path .exists (pywin32_filename ):
53
- url = pywin32_base + pywin32_filename
54
- print ('Downloading pywin32: ' + url )
55
- urllib .request .urlretrieve (url , pywin32_filename )
60
+ python_arch = find_python_arch ()
61
+ package_name = 'pythonarm64' if python_arch == 'arm64' else 'python'
62
+ download_url = f'https://www.nuget.org/api/v2/package/{ package_name } /{ version } '
63
+ filename = f'python-{ version } -win-{ python_arch } .zip'
64
+ out_filename = f'python-{ version } -{ revision } -win-{ python_arch } .zip'
56
65
57
66
if not os .path .exists (filename ):
58
67
print (f'Downloading python: { download_url } to { filename } ' )
@@ -62,19 +71,17 @@ def make_python_patch():
62
71
check_call (unzip_cmd () + [os .path .abspath (filename )], cwd = 'python-nuget' )
63
72
os .remove (filename )
64
73
65
- os .mkdir ('pywin32' )
66
- rtn = subprocess .call (unzip_cmd () + [os .path .abspath (pywin32_filename )], cwd = 'pywin32' )
67
- assert rtn in [0 , 1 ]
68
-
69
- os .mkdir (os .path .join ('python-nuget' , 'lib' ))
70
- shutil .move (os .path .join ('pywin32' , 'PLATLIB' ), os .path .join ('python-nuget' , 'toolss' , 'Lib' , 'site-packages' ))
74
+ src_dir = os .path .join ('python-nuget' , 'tools' )
75
+ python_exe = os .path .join (src_dir , 'python.exe' )
76
+ check_call ([python_exe , '-m' , 'ensurepip' , '--upgrade' ])
77
+ check_call ([python_exe , '-m' , 'pip' , 'install' , 'pywin32==310' , '--no-warn-script-location' ])
78
+ check_call ([python_exe , '-m' , 'pip' , 'install' , PSUTIL ])
71
79
72
- check_call (zip_cmd () + [os .path .join ('..' , '..' , out_filename ), '.' ], cwd = 'python-nuget/tools' )
80
+ check_call (zip_cmd () + [os .path .join ('..' , '..' , out_filename ), '.' ], cwd = src_dir )
73
81
print ('Created: %s' % out_filename )
74
82
75
83
# cleanup if everything went fine
76
84
shutil .rmtree ('python-nuget' )
77
- shutil .rmtree ('pywin32' )
78
85
79
86
if '--upload' in sys .argv :
80
87
upload_url = upload_base + out_filename
@@ -92,7 +99,7 @@ def build_python():
92
99
check_call (['brew' , 'install' , 'openssl' , 'xz' , 'pkg-config' ])
93
100
if platform .machine () == 'x86_64' :
94
101
prefix = '/usr/local'
95
- min_macos_version = '10.11 '
102
+ min_macos_version = '11.0 '
96
103
elif platform .machine () == 'arm64' :
97
104
prefix = '/opt/homebrew'
98
105
min_macos_version = '11.0'
@@ -113,7 +120,9 @@ def build_python():
113
120
osname = 'linux'
114
121
115
122
src_dir = 'cpython'
116
- if not os .path .exists (src_dir ):
123
+ if os .path .exists (src_dir ):
124
+ check_call (['git' , 'fetch' ], cwd = src_dir )
125
+ else :
117
126
check_call (['git' , 'clone' , 'https://github.com/python/cpython' ])
118
127
check_call (['git' , 'checkout' , 'v' + version ], cwd = src_dir )
119
128
@@ -143,7 +152,7 @@ def build_python():
143
152
144
153
# Install psutil module. This is needed by emrun to track when browser
145
154
# process quits.
146
- check_call ([pybin , pip , 'install' , 'psutil' ])
155
+ check_call ([pybin , pip , 'install' , PSUTIL ])
147
156
148
157
dirname = 'python-%s-%s' % (version , revision )
149
158
if os .path .isdir (dirname ):
0 commit comments