Building PyPy wheels on Windows

This commit is contained in:
Yannick Jadoul
2020-02-15 23:24:51 +01:00
parent dd26ef8ac6
commit 129cf601da
2 changed files with 45 additions and 19 deletions
+38 -16
View File
@@ -4,6 +4,7 @@ import subprocess
import tempfile
from collections import namedtuple
from glob import glob
from zipfile import ZipFile
from .util import (
download,
@@ -16,9 +17,14 @@ IS_RUNNING_ON_AZURE = os.path.exists('C:\\hostedtoolcache')
IS_RUNNING_ON_TRAVIS = os.environ.get('TRAVIS_OS_NAME') == 'windows'
def get_python_path(config):
nuget_args = get_nuget_args(config)
return os.path.join(nuget_args[-1], nuget_args[0] + "." + config.version, "tools")
def get_python_path(config):
if config.identifier.startswith('cp'):
nuget_args = get_nuget_args(config)
return os.path.join(nuget_args[-1], nuget_args[0] + "." + config.version, "tools")
elif config.identifier.startswith('pp'):
# Inside the PyPy zip file is a directory with the same name
filename = config.url.rsplit('/', 1)[-1]
return os.path.join("C:\\PyPy", os.path.splitext(filename)[0])
def get_nuget_args(configuration):
@@ -29,24 +35,26 @@ def get_nuget_args(configuration):
def get_python_configurations(build_selector):
PythonConfiguration = namedtuple('PythonConfiguration', ['version', 'arch', 'identifier'])
PythonConfiguration = namedtuple('PythonConfiguration', ['version', 'arch', 'identifier', 'url'])
python_configurations = [
PythonConfiguration(version='2.7.17', arch="32", identifier='cp27-win32'),
PythonConfiguration(version='2.7.17', arch="64", identifier='cp27-win_amd64'),
PythonConfiguration(version='3.5.4', arch="32", identifier='cp35-win32'),
PythonConfiguration(version='3.5.4', arch="64", identifier='cp35-win_amd64'),
PythonConfiguration(version='3.6.8', arch="32", identifier='cp36-win32'),
PythonConfiguration(version='3.6.8', arch="64", identifier='cp36-win_amd64'),
PythonConfiguration(version='3.7.6', arch="32", identifier='cp37-win32'),
PythonConfiguration(version='3.7.6', arch="64", identifier='cp37-win_amd64'),
PythonConfiguration(version='3.8.1', arch="32", identifier='cp38-win32'),
PythonConfiguration(version='3.8.1', arch="64", identifier='cp38-win_amd64'),
PythonConfiguration(version='2.7.17', arch="32", identifier='cp27-win32', url=None),
PythonConfiguration(version='2.7.17', arch="64", identifier='cp27-win_amd64', url=None),
PythonConfiguration(version='3.5.4', arch="32", identifier='cp35-win32', url=None),
PythonConfiguration(version='3.5.4', arch="64", identifier='cp35-win_amd64', url=None),
PythonConfiguration(version='3.6.8', arch="32", identifier='cp36-win32', url=None),
PythonConfiguration(version='3.6.8', arch="64", identifier='cp36-win_amd64', url=None),
PythonConfiguration(version='3.7.6', arch="32", identifier='cp37-win32', url=None),
PythonConfiguration(version='3.7.6', arch="64", identifier='cp37-win_amd64', url=None),
PythonConfiguration(version='3.8.1', arch="32", identifier='cp38-win32', url=None),
PythonConfiguration(version='3.8.1', arch="64", identifier='cp38-win_amd64', url=None),
PythonConfiguration(version='2.7-v7.2.0', arch="32", identifier='pp272-win32', url='https://bitbucket.org/pypy/pypy/downloads/pypy2.7-v7.2.0-win32.zip'),
PythonConfiguration(version='3.6-v7.2.0', arch="32", identifier='pp372-win32', url='https://bitbucket.org/pypy/pypy/downloads/pypy3.6-v7.2.0-win32.zip'),
]
if IS_RUNNING_ON_TRAVIS:
# cannot install VCForPython27.msi which is needed for compiling C software
# try with (and similar): msiexec /i VCForPython27.msi ALLUSERS=1 ACCEPT=YES /passive
python_configurations = [c for c in python_configurations if not c.version.startswith('2.7.')]
python_configurations = [c for c in python_configurations if not c.version.startswith('2.7')]
# skip builds as required
python_configurations = [c for c in python_configurations if build_selector(c.identifier)]
@@ -60,6 +68,10 @@ def build(project_dir, output_dir, test_command, test_requires, test_extras, bef
args = ['cmd', '/E:ON', '/V:ON', '/C'] + args
return subprocess.check_call(' '.join(args), env=env, cwd=cwd)
def extract_zip(zip_src, dest):
with ZipFile(zip_src) as zip:
zip.extractall(dest)
if IS_RUNNING_ON_AZURE or IS_RUNNING_ON_TRAVIS:
shell = simple_shell
else:
@@ -89,7 +101,17 @@ def build(project_dir, output_dir, test_command, test_requires, test_extras, bef
for config in python_configurations:
# install Python
config_python_path = get_python_path(config)
simple_shell([nuget, "install"] + get_nuget_args(config))
if config.identifier.startswith('cp'):
simple_shell([nuget, "install"] + get_nuget_args(config))
elif config.identifier.startswith('pp') and not os.path.exists(config_python_path):
pypy_zip = config.url.rsplit('/', 1)[-1]
download(config.url, pypy_zip)
# Extract to the parent of config_python_path because the zip file still contains a directory
extract_zip(pypy_zip, os.path.dirname(config_python_path))
pypy_exe = 'pypy.exe' if config.version[0] == '2' else 'pypy3.exe'
simple_shell(['mklink', os.path.join(config_python_path, 'python.exe'), os.path.join(config_python_path, pypy_exe)])
simple_shell(['mklink', '/d', os.path.join(config_python_path, 'Scripts'), os.path.join(config_python_path, 'bin')])
simple_shell(['chcp', '437']) # Workaround for https://bitbucket.org/pypy/pypy/issues/3081/
assert os.path.exists(os.path.join(config_python_path, 'python.exe'))
# set up PATH and environment variables for run_with_env
+7 -3
View File
@@ -98,9 +98,13 @@ def expected_wheels(package_name, package_version, manylinux_versions=['manylinu
for manylinux_version in manylinux_versions
for architecture in architectures]
elif platform == 'windows':
# Second step: adding PyPy support on Windows
python_abi_tags.extend(['pp272-pypy_41', 'pp372-pp372'])
def get_platform_tags(python_abi_tag):
return ['win32', 'win_amd64']
if python_abi_tag.startswith('pp'):
return ['win32']
else:
return ['win32', 'win_amd64']
elif platform == 'macos':
@@ -120,7 +124,7 @@ def expected_wheels(package_name, package_version, manylinux_versions=['manylinu
if IS_WINDOWS_RUNNING_ON_TRAVIS:
# Python 2.7 isn't supported on Travis.
templates = [t for t in templates if '-cp27-' not in t]
templates = [t for t in templates if '-cp27-' not in t and '-pp2' not in t]
return templates