Build Python wheels for windows on travis (#160)
* upgrade for windows on travis * Install python on travis windows, update readme, update tests * update readme, travis config and clean code * install python inside cibuildwheel run * use register to get python path * fixes from review * fix pip version * use nuget for instal python * clean code * Update cibuildwheel/windows.py Co-Authored-By: Joe Rickerby <joerick@mac.com> * fixes from review * Final bits of tidy up
This commit is contained in:
committed by
Joe Rickerby
co-authored by
Joe Rickerby
parent
4f705b7cc9
commit
80974e5b39
@@ -27,6 +27,15 @@ matrix:
|
||||
- brew update
|
||||
- brew outdated python || brew upgrade python
|
||||
|
||||
- os: windows
|
||||
language: shell
|
||||
before_install:
|
||||
- choco install python3 --version 3.6.8 --no-progress -y
|
||||
install:
|
||||
- C:\\Python36\\python -m pip install -r requirements-dev.txt
|
||||
script:
|
||||
- C:\\Python36\\python ./bin/run_tests.py
|
||||
|
||||
install: $PYTHON -m pip install -r requirements-dev.txt
|
||||
|
||||
script: $PYTHON ./bin/run_tests.py
|
||||
|
||||
@@ -14,13 +14,15 @@ What does it do?
|
||||
|
||||
| | macOS 10.6+ | manylinux i686 | manylinux x86_64 | Windows 32bit | Windows 64bit |
|
||||
|---|---|---|---|---|---|
|
||||
| Python 2.7 | ✅ | ✅ | ✅ | ✅ | ✅ |
|
||||
| Python 3.4 | ✅ | ✅ | ✅ | ✅* | ✅* |
|
||||
| Python 2.7 | ✅ | ✅ | ✅ | ✅² | ✅² |
|
||||
| Python 3.4 | ✅ | ✅ | ✅ | ✅¹²| ✅¹²|
|
||||
| Python 3.5 | ✅ | ✅ | ✅ | ✅ | ✅ |
|
||||
| Python 3.6 | ✅ | ✅ | ✅ | ✅ | ✅ |
|
||||
| Python 3.7 | ✅ | ✅ | ✅ | ✅ | ✅ |
|
||||
|
||||
> \* Not supported on Azure Pipelines
|
||||
> ¹ Not supported on Azure Pipelines
|
||||
>
|
||||
> ² Not supported on Travis
|
||||
|
||||
- Builds manylinux, macOS and Windows (32 and 64bit) wheels using Azure Pipelines, Travis CI, AppVeyor, and CircleCI
|
||||
- Bundles shared library dependencies on Linux and macOS through [auditwheel](https://github.com/pypa/auditwheel) and [delocate](https://github.com/matthew-brett/delocate)
|
||||
@@ -34,7 +36,7 @@ Usage
|
||||
| | Linux | macOS | Windows |
|
||||
|-----------------|-------|-------|---------|
|
||||
| Azure Pipelines | ✅ | ✅ | ✅ |
|
||||
| Travis CI | ✅ | ✅ | |
|
||||
| Travis CI | ✅ | ✅ | ✅ |
|
||||
| AppVeyor | | | ✅ |
|
||||
| CircleCI | ✅ | ✅ | |
|
||||
|
||||
@@ -101,11 +103,12 @@ jobs:
|
||||
<summary><b>Travis CI</b>
|
||||
<img width="16" src="https://unpkg.com/simple-icons@latest/icons/apple.svg" />
|
||||
<img width="16" src="https://unpkg.com/simple-icons@latest/icons/linux.svg" />
|
||||
<img width="16" src="https://unpkg.com/simple-icons@latest/icons/windows.svg" />
|
||||
</summary>
|
||||
|
||||
- To build Linux and Mac wheels on Travis CI, create a `.travis.yml` file in your repo.
|
||||
|
||||
```
|
||||
```yaml
|
||||
language: python
|
||||
|
||||
matrix:
|
||||
@@ -123,6 +126,18 @@ jobs:
|
||||
- cibuildwheel --output-dir wheelhouse
|
||||
```
|
||||
|
||||
To build on Windows too, add this matrix entry:
|
||||
```yaml
|
||||
- os: windows
|
||||
language: shell
|
||||
before_install:
|
||||
- choco install python3 --version 3.6.8 --no-progress -y
|
||||
env:
|
||||
- PATH=/c/Python36:/c/Python36/Scripts:$PATH
|
||||
```
|
||||
|
||||
Note that building Windows Python 2.7 wheels on Travis is unsupported.
|
||||
|
||||
Then setup a deployment method by following the [Travis CI deployment docs](https://docs.travis-ci.com/user/deployment/), or see [Delivering to PyPI](#delivering-to-pypi) below.
|
||||
|
||||
</details>
|
||||
|
||||
@@ -65,6 +65,8 @@ def main():
|
||||
platform = 'linux'
|
||||
elif os.environ.get('TRAVIS_OS_NAME') == 'osx':
|
||||
platform = 'macos'
|
||||
elif os.environ.get('TRAVIS_OS_NAME') == 'windows':
|
||||
platform = 'windows'
|
||||
elif 'APPVEYOR' in os.environ:
|
||||
platform = 'windows'
|
||||
elif 'BITRISE_BUILD_NUMBER' in os.environ:
|
||||
|
||||
+61
-17
@@ -1,12 +1,18 @@
|
||||
from __future__ import print_function
|
||||
import os, tempfile, subprocess, shutil
|
||||
import os, tempfile, subprocess, shutil, sys
|
||||
from collections import namedtuple
|
||||
from glob import glob
|
||||
|
||||
try:
|
||||
from shlex import quote as shlex_quote
|
||||
except ImportError:
|
||||
from pipes import quote as shlex_quote
|
||||
|
||||
from .util import prepare_command, get_build_verbosity_extra_flags
|
||||
|
||||
|
||||
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):
|
||||
if IS_RUNNING_ON_AZURE:
|
||||
@@ -22,6 +28,12 @@ def get_python_path(config):
|
||||
return glob(path_pattern)[0]
|
||||
except IndexError:
|
||||
raise Exception('Could not find a Python install at ' + path_pattern)
|
||||
elif IS_RUNNING_ON_TRAVIS:
|
||||
if config.version == "3.4.x":
|
||||
return config.path
|
||||
else:
|
||||
nuget_args = get_nuget_args(config)
|
||||
return os.path.join(nuget_args[-1], nuget_args[0] + "." + config.nuget_version, "tools")
|
||||
else:
|
||||
# Assume we're running on AppVeyor
|
||||
major, minor = config.version.split('.')[:2]
|
||||
@@ -32,32 +44,49 @@ def get_python_path(config):
|
||||
)
|
||||
|
||||
|
||||
def get_nuget_args(configuration):
|
||||
if configuration.nuget_version is None:
|
||||
return None
|
||||
python_name = "python" if configuration.version[0] == '3' else "python2"
|
||||
if configuration.arch == "32":
|
||||
python_name = python_name + "x86"
|
||||
return [python_name, "-Version", configuration.nuget_version, "-OutputDirectory", "C:/python"]
|
||||
|
||||
def get_python_configurations(build_selector):
|
||||
PythonConfiguration = namedtuple('PythonConfiguration', ['version', 'arch', 'identifier', 'path'])
|
||||
PythonConfiguration = namedtuple('PythonConfiguration', ['version', 'arch', 'identifier', 'path', "nuget_version"])
|
||||
python_configurations = [
|
||||
PythonConfiguration(version='2.7.x', arch="32", identifier='cp27-win32', path='C:\Python27'),
|
||||
PythonConfiguration(version='2.7.x', arch="64", identifier='cp27-win_amd64', path='C:\Python27-x64'),
|
||||
PythonConfiguration(version='3.4.x', arch="32", identifier='cp34-win32', path='C:\Python34'),
|
||||
PythonConfiguration(version='3.4.x', arch="64", identifier='cp34-win_amd64', path='C:\Python34-x64'),
|
||||
PythonConfiguration(version='3.5.x', arch="32", identifier='cp35-win32', path='C:\Python35'),
|
||||
PythonConfiguration(version='3.5.x', arch="64", identifier='cp35-win_amd64', path='C:\Python35-x64'),
|
||||
PythonConfiguration(version='3.6.x', arch="32", identifier='cp36-win32', path='C:\Python36'),
|
||||
PythonConfiguration(version='3.6.x', arch="64", identifier='cp36-win_amd64', path='C:\Python36-x64'),
|
||||
PythonConfiguration(version='3.7.x', arch="32", identifier='cp37-win32', path='C:\Python37'),
|
||||
PythonConfiguration(version='3.7.x', arch="64", identifier='cp37-win_amd64', path='C:\Python37-x64'),
|
||||
PythonConfiguration(version='2.7.x', arch="32", identifier='cp27-win32', path='C:\\Python27', nuget_version="2.7.16"),
|
||||
PythonConfiguration(version='2.7.x', arch="64", identifier='cp27-win_amd64', path='C:\\Python27-x64', nuget_version="2.7.16"),
|
||||
PythonConfiguration(version='3.4.x', arch="32", identifier='cp34-win32', path='C:\\Python34', nuget_version=None),
|
||||
PythonConfiguration(version='3.4.x', arch="64", identifier='cp34-win_amd64', path='C:\\Python34-x64', nuget_version=None),
|
||||
PythonConfiguration(version='3.5.x', arch="32", identifier='cp35-win32', path='C:\\Python35', nuget_version="3.5.4"),
|
||||
PythonConfiguration(version='3.5.x', arch="64", identifier='cp35-win_amd64', path='C:\\Python35-x64', nuget_version="3.5.4"),
|
||||
PythonConfiguration(version='3.6.x', arch="32", identifier='cp36-win32', path='C:\\Python36', nuget_version="3.6.8"),
|
||||
PythonConfiguration(version='3.6.x', arch="64", identifier='cp36-win_amd64', path='C:\\Python36-x64', nuget_version="3.6.8"),
|
||||
PythonConfiguration(version='3.7.x', arch="32", identifier='cp37-win32', path='C:\\Python37', nuget_version="3.7.4"),
|
||||
PythonConfiguration(version='3.7.x', arch="64", identifier='cp37-win_amd64', path='C:\\Python37-x64', nuget_version="3.7.4")
|
||||
]
|
||||
|
||||
if IS_RUNNING_ON_AZURE:
|
||||
# Python 3.4 isn't supported on Azure.
|
||||
# See https://github.com/Microsoft/azure-pipelines-tasks/issues/9674
|
||||
python_configurations = [c for c in python_configurations if c.version != '3.4.x']
|
||||
|
||||
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
|
||||
# no easy and stable way fo installing python 3.4
|
||||
python_configurations = [c for c in python_configurations if c.version != '2.7.x' and c.version != '3.4.x']
|
||||
|
||||
# skip builds as required
|
||||
python_configurations = [c for c in python_configurations if build_selector(c.identifier)]
|
||||
|
||||
return python_configurations
|
||||
|
||||
# skip builds as required
|
||||
return [c for c in python_configurations if build_selector(c.identifier)]
|
||||
|
||||
|
||||
def build(project_dir, output_dir, test_command, test_requires, test_extras, before_build, build_verbosity, build_selector, environment):
|
||||
if IS_RUNNING_ON_AZURE:
|
||||
if IS_RUNNING_ON_AZURE or IS_RUNNING_ON_TRAVIS:
|
||||
def shell(args, env=None, cwd=None):
|
||||
print('+ ' + ' '.join(args))
|
||||
args = ['cmd', '/E:ON', '/V:ON', '/C'] + args
|
||||
@@ -77,10 +106,21 @@ def build(project_dir, output_dir, test_command, test_requires, test_extras, bef
|
||||
temp_dir = tempfile.mkdtemp(prefix='cibuildwheel')
|
||||
built_wheel_dir = os.path.join(temp_dir, 'built_wheel')
|
||||
|
||||
python_configurations = get_python_configurations(build_selector)
|
||||
if IS_RUNNING_ON_TRAVIS:
|
||||
# instal nuget as best way for provide python
|
||||
shell(["choco", "install", "nuget.commandline"])
|
||||
# get pip fo this installation which not have.
|
||||
get_pip_url = 'https://bootstrap.pypa.io/get-pip.py'
|
||||
get_pip_script = 'C:\\get-pip.py'
|
||||
shell(['curl', '-L', '-o', get_pip_script, get_pip_url])
|
||||
|
||||
python_configurations = get_python_configurations(build_selector)
|
||||
for config in python_configurations:
|
||||
config_python_path = get_python_path(config)
|
||||
if IS_RUNNING_ON_TRAVIS and config.nuget_version is not None and not os.path.exists(config_python_path):
|
||||
shell(["nuget", "install"] + get_nuget_args(config))
|
||||
if not os.path.exists(os.path.join(config_python_path, 'Scripts', 'pip.exe')):
|
||||
shell([os.path.join(config_python_path, 'python.exe'), get_pip_script ])
|
||||
|
||||
# check python & pip exist for this configuration
|
||||
assert os.path.exists(os.path.join(config_python_path, 'python.exe'))
|
||||
@@ -107,8 +147,12 @@ def build(project_dir, output_dir, test_command, test_requires, test_extras, bef
|
||||
shell(['python', '-c', '"import struct; print(struct.calcsize(\'P\') * 8)\"'], env=env)
|
||||
|
||||
# prepare the Python environment
|
||||
shell(['python', '-m', 'pip', 'install', '--upgrade', 'pip'],
|
||||
if config.version == "3.4.x":
|
||||
shell(['python', '-m', 'pip', 'install', 'pip==19.1.1'],
|
||||
env=env)
|
||||
else:
|
||||
shell(['python', '-m', 'pip', 'install', '--upgrade', 'pip'],
|
||||
env=env)
|
||||
shell(['pip', 'install', '--upgrade', 'setuptools'], env=env)
|
||||
shell(['pip', 'install', 'wheel'], env=env)
|
||||
|
||||
|
||||
@@ -6,7 +6,8 @@ This file is added to the PYTHONPATH in the test runner at bin/run_test.py.
|
||||
|
||||
import subprocess, sys, os
|
||||
|
||||
IS_RUNNING_ON_AZURE = os.path.exists('C:\\hostedtoolcache')
|
||||
IS_WINDOWS_RUNNING_ON_AZURE = os.path.exists('C:\\hostedtoolcache')
|
||||
IS_WINDOWS_RUNNING_ON_TRAVIS = os.environ.get('TRAVIS_OS_NAME') == 'windows'
|
||||
|
||||
|
||||
def cibuildwheel_get_build_identifiers(project_path, env=None):
|
||||
@@ -97,9 +98,12 @@ def expected_wheels(package_name, package_version):
|
||||
else:
|
||||
raise Exception('unsupported platform')
|
||||
|
||||
if IS_RUNNING_ON_AZURE:
|
||||
if IS_WINDOWS_RUNNING_ON_AZURE:
|
||||
# Python 3.4 isn't supported on Azure.
|
||||
templates = [t for t in templates if '-cp34-' not in t]
|
||||
if IS_WINDOWS_RUNNING_ON_TRAVIS:
|
||||
# Python 2.7 and 3.4 isn't supported on Travis.
|
||||
templates = [t for t in templates if '-cp27-' not in t and '-cp34-' not in t]
|
||||
|
||||
return [filename.format(package_name=package_name, package_version=package_version)
|
||||
for filename in templates]
|
||||
|
||||
Reference in New Issue
Block a user