Merge remote-tracking branch 'origin/master' into docs

This commit is contained in:
Joe Rickerby
2019-11-09 18:23:41 +00:00
12 changed files with 117 additions and 148 deletions
+1 -1
View File
@@ -12,7 +12,7 @@ matrix:
# Linux Python 3 # Linux Python 3
- sudo: required - sudo: required
language: python language: python
python: 3.4 python: 3.5
services: docker services: docker
env: PYTHON=python env: PYTHON=python
+13 -15
View File
@@ -15,17 +15,15 @@ Python wheels are great. Building them across **Mac, Linux, Windows**, on **mult
What does it do? What does it do?
---------------- ----------------
| | macOS 10.6+ | manylinux i686 | manylinux x86_64 | Windows 32bit | Windows 64bit | | | macOS 10.6+ intel | macOS 10.9+ x86_64 | manylinux i686 | manylinux x86_64 | Windows 32bit | Windows 64bit |
|---|---|---|---|---|---| |---|---|---|---|---|---|---|
| Python 2.7 | ✅ | ✅ | ✅ | ✅² | ✅² | | Python 2.7 | ✅ | | ✅ | ✅ | ✅¹ | ✅¹ |
| Python 3.4 | ✅ | ✅ | ✅ | ✅¹²| ✅¹²| | Python 3.5 | ✅ | | ✅ | ✅ | ✅ | ✅ |
| Python 3.5 | ✅ | ✅ | ✅ | ✅ | ✅ | | Python 3.6 | ✅ | | ✅ | ✅ | ✅ | ✅ |
| Python 3.6 | ✅ | ✅ | ✅ | ✅ | ✅ | | Python 3.7 | ✅ | | ✅ | ✅ | ✅ | ✅ |
| Python 3.7 | ✅ | ✅ | ✅ | ✅ | ✅ | | Python 3.8 | | ✅ | ✅ | ✅ | ✅ | ✅ |
> ¹ Not supported on Azure Pipelines > ¹ Not supported on Travis
>
> ² Not supported on Travis
- Builds manylinux, macOS and Windows (32 and 64bit) wheels using Azure Pipelines, Travis CI, AppVeyor, and CircleCI - 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) - Bundles shared library dependencies on Linux and macOS through [auditwheel](https://github.com/pypa/auditwheel) and [delocate](https://github.com/matthew-brett/delocate)
@@ -91,7 +89,7 @@ For more information, including how to build on Appveyor, Azure, CircleCI, check
Working examples Working examples
---------------- ----------------
Here are some repos that use cibuildwheel. Here are some repos that use cibuildwheel.
- [pyinstrument_cext](https://github.com/joerick/pyinstrument_cext) - [pyinstrument_cext](https://github.com/joerick/pyinstrument_cext)
- [websockets](https://github.com/aaugustin/websockets) - [websockets](https://github.com/aaugustin/websockets)
@@ -109,7 +107,7 @@ Here are some repos that use cibuildwheel.
Legal note Legal note
---------- ----------
Since `cibuildwheel` runs the wheel through delocate or auditwheel, it might automatically bundle dynamically linked libraries from the build machine. Since `cibuildwheel` runs the wheel through delocate or auditwheel, it might automatically bundle dynamically linked libraries from the build machine.
It helps ensure that the library can run without any dependencies outside of the pip toolchain. It helps ensure that the library can run without any dependencies outside of the pip toolchain.
@@ -141,7 +139,7 @@ _26 May 2019_
- ✨ Add support for building on Azure pipelines! This lets you build all - ✨ Add support for building on Azure pipelines! This lets you build all
Linux, Mac and Windows wheels on one service, so it promises to be the Linux, Mac and Windows wheels on one service, so it promises to be the
easiest to set up! Check out the quickstart in the docs, or easiest to set up! Check out the quickstart in the docs, or
[cibuildwheel-azure-example](https://github.com/joerick/cibuildwheel-azure-example) [cibuildwheel-azure-example](https://github.com/joerick/cibuildwheel-azure-example)
for an example project. (#126, #132) for an example project. (#126, #132)
- 🛠 Internal change - the end-to-end test projects format was updated, so we - 🛠 Internal change - the end-to-end test projects format was updated, so we
@@ -281,7 +279,7 @@ _11 June 2017_
_13 April 2017_ _13 April 2017_
- ✨ Added `CIBW_SKIP` option, letting users explicitly skip a build - ✨ Added `CIBW_SKIP` option, letting users explicitly skip a build
- ✨ Added `CIBW_BEFORE_BUILD` option, letting users run a shell command before the build starts - ✨ Added `CIBW_BEFORE_BUILD` option, letting users run a shell command before the build starts
### 0.1.3 ### 0.1.3
@@ -306,7 +304,7 @@ Maintainers
Credits Credits
------- -------
`cibuildwheel` stands on the shoulders of giants. `cibuildwheel` stands on the shoulders of giants.
- ⭐️ @matthew-brett for [matthew-brett/multibuild](http://github.com/matthew-brett/multibuild) and [matthew-brett/delocate](http://github.com/matthew-brett/delocate) - ⭐️ @matthew-brett for [matthew-brett/multibuild](http://github.com/matthew-brett/multibuild) and [matthew-brett/delocate](http://github.com/matthew-brett/delocate)
- @PyPA for the manylinux Docker images [pypa/manylinux](https://github.com/pypa/manylinux) - @PyPA for the manylinux Docker images [pypa/manylinux](https://github.com/pypa/manylinux)
+11 -12
View File
@@ -1,31 +1,30 @@
jobs: jobs:
- job: linux - job: linux
pool: {vmImage: 'Ubuntu-16.04'} pool: {vmImage: 'Ubuntu-18.04'}
steps: steps:
- task: UsePythonVersion@0 - task: UsePythonVersion@0
inputs:
versionSpec: '3.8'
- bash: | - bash: |
python -m pip install -r requirements-dev.txt python -m pip install -r requirements-dev.txt
python ./bin/run_tests.py python ./bin/run_tests.py
- job: macos - job: macos
pool: {vmImage: 'macOS-10.13'} pool: {vmImage: 'macOS-10.13'}
steps: steps:
- task: UsePythonVersion@0 - task: UsePythonVersion@0
inputs:
versionSpec: '3.8'
- bash: | - bash: |
python -m pip install -r requirements-dev.txt python -m pip install -r requirements-dev.txt
python ./bin/run_tests.py python ./bin/run_tests.py
- job: windows - job: windows
pool: {vmImage: 'vs2017-win2016'} pool: {vmImage: 'vs2017-win2016'}
steps: steps:
- {task: UsePythonVersion@0, inputs: {versionSpec: '2.7', architecture: x86}} - task: UsePythonVersion@0
- {task: UsePythonVersion@0, inputs: {versionSpec: '2.7', architecture: x64}} inputs:
- {task: UsePythonVersion@0, inputs: {versionSpec: '3.5', architecture: x86}} versionSpec: '3.8'
- {task: UsePythonVersion@0, inputs: {versionSpec: '3.5', architecture: x64}}
- {task: UsePythonVersion@0, inputs: {versionSpec: '3.6', architecture: x86}}
- {task: UsePythonVersion@0, inputs: {versionSpec: '3.6', architecture: x64}}
- {task: UsePythonVersion@0, inputs: {versionSpec: '3.7', architecture: x86}}
- {task: UsePythonVersion@0, inputs: {versionSpec: '3.7', architecture: x64}}
- script: choco install vcpython27 -f -y - script: choco install vcpython27 -f -y
displayName: Install Visual C++ for Python 2.7 displayName: Install Visual C++ for Python 2.7
- bash: | - bash: |
+2 -2
View File
@@ -14,16 +14,16 @@ def get_python_configurations(build_selector):
python_configurations = [ python_configurations = [
PythonConfiguration(identifier='cp27-manylinux_x86_64', path='/opt/python/cp27-cp27m'), PythonConfiguration(identifier='cp27-manylinux_x86_64', path='/opt/python/cp27-cp27m'),
PythonConfiguration(identifier='cp27-manylinux_x86_64', path='/opt/python/cp27-cp27mu'), PythonConfiguration(identifier='cp27-manylinux_x86_64', path='/opt/python/cp27-cp27mu'),
PythonConfiguration(identifier='cp34-manylinux_x86_64', path='/opt/python/cp34-cp34m'),
PythonConfiguration(identifier='cp35-manylinux_x86_64', path='/opt/python/cp35-cp35m'), PythonConfiguration(identifier='cp35-manylinux_x86_64', path='/opt/python/cp35-cp35m'),
PythonConfiguration(identifier='cp36-manylinux_x86_64', path='/opt/python/cp36-cp36m'), PythonConfiguration(identifier='cp36-manylinux_x86_64', path='/opt/python/cp36-cp36m'),
PythonConfiguration(identifier='cp37-manylinux_x86_64', path='/opt/python/cp37-cp37m'), PythonConfiguration(identifier='cp37-manylinux_x86_64', path='/opt/python/cp37-cp37m'),
PythonConfiguration(identifier='cp38-manylinux_x86_64', path='/opt/python/cp38-cp38'),
PythonConfiguration(identifier='cp27-manylinux_i686', path='/opt/python/cp27-cp27m'), PythonConfiguration(identifier='cp27-manylinux_i686', path='/opt/python/cp27-cp27m'),
PythonConfiguration(identifier='cp27-manylinux_i686', path='/opt/python/cp27-cp27mu'), PythonConfiguration(identifier='cp27-manylinux_i686', path='/opt/python/cp27-cp27mu'),
PythonConfiguration(identifier='cp34-manylinux_i686', path='/opt/python/cp34-cp34m'),
PythonConfiguration(identifier='cp35-manylinux_i686', path='/opt/python/cp35-cp35m'), PythonConfiguration(identifier='cp35-manylinux_i686', path='/opt/python/cp35-cp35m'),
PythonConfiguration(identifier='cp36-manylinux_i686', path='/opt/python/cp36-cp36m'), PythonConfiguration(identifier='cp36-manylinux_i686', path='/opt/python/cp36-cp36m'),
PythonConfiguration(identifier='cp37-manylinux_i686', path='/opt/python/cp37-cp37m'), PythonConfiguration(identifier='cp37-manylinux_i686', path='/opt/python/cp37-cp37m'),
PythonConfiguration(identifier='cp38-manylinux_i686', path='/opt/python/cp38-cp38'),
] ]
# skip builds as required # skip builds as required
+2 -2
View File
@@ -15,10 +15,10 @@ def get_python_configurations(build_selector):
PythonConfiguration = namedtuple('PythonConfiguration', ['version', 'identifier', 'url']) PythonConfiguration = namedtuple('PythonConfiguration', ['version', 'identifier', 'url'])
python_configurations = [ python_configurations = [
PythonConfiguration(version='2.7', identifier='cp27-macosx_10_6_intel', url='https://www.python.org/ftp/python/2.7.17/python-2.7.17-macosx10.6.pkg'), PythonConfiguration(version='2.7', identifier='cp27-macosx_10_6_intel', url='https://www.python.org/ftp/python/2.7.17/python-2.7.17-macosx10.6.pkg'),
PythonConfiguration(version='3.4', identifier='cp34-macosx_10_6_intel', url='https://www.python.org/ftp/python/3.4.4/python-3.4.4-macosx10.6.pkg'),
PythonConfiguration(version='3.5', identifier='cp35-macosx_10_6_intel', url='https://www.python.org/ftp/python/3.5.4/python-3.5.4-macosx10.6.pkg'), PythonConfiguration(version='3.5', identifier='cp35-macosx_10_6_intel', url='https://www.python.org/ftp/python/3.5.4/python-3.5.4-macosx10.6.pkg'),
PythonConfiguration(version='3.6', identifier='cp36-macosx_10_6_intel', url='https://www.python.org/ftp/python/3.6.8/python-3.6.8-macosx10.6.pkg'), PythonConfiguration(version='3.6', identifier='cp36-macosx_10_6_intel', url='https://www.python.org/ftp/python/3.6.8/python-3.6.8-macosx10.6.pkg'),
PythonConfiguration(version='3.7', identifier='cp37-macosx_10_6_intel', url='https://www.python.org/ftp/python/3.7.5/python-3.7.5-macosx10.6.pkg'), PythonConfiguration(version='3.7', identifier='cp37-macosx_10_6_intel', url='https://www.python.org/ftp/python/3.7.5/python-3.7.5-macosx10.6.pkg'),
PythonConfiguration(version='3.8', identifier='cp38-macosx_10_9_x86_64', url='https://www.python.org/ftp/python/3.8.0/python-3.8.0-macosx10.9.pkg'),
] ]
# skip builds as required # skip builds as required
@@ -58,7 +58,7 @@ def build(project_dir, output_dir, test_command, test_requires, test_extras, bef
# install # install
call(['sudo', 'installer', '-pkg', '/tmp/Python.pkg', '-target', '/']) call(['sudo', 'installer', '-pkg', '/tmp/Python.pkg', '-target', '/'])
# patch open ssl # patch open ssl
if config.version in ('3.4', '3.5'): if config.version == '3.5':
call(['curl', '-fsSLo', '/tmp/python-patch.tar.gz', 'https://github.com/mayeut/patch-macos-python-openssl/releases/download/v1.0.2t/patch-macos-python-%s-openssl-v1.0.2t.tar.gz' % config.version]) call(['curl', '-fsSLo', '/tmp/python-patch.tar.gz', 'https://github.com/mayeut/patch-macos-python-openssl/releases/download/v1.0.2t/patch-macos-python-%s-openssl-v1.0.2t.tar.gz' % config.version])
call(['sudo', 'tar', '-C', '/Library/Frameworks/Python.framework/Versions/%s/' % config.version, '-xmf', '/tmp/python-patch.tar.gz']) call(['sudo', 'tar', '-C', '/Library/Frameworks/Python.framework/Versions/%s/' % config.version, '-xmf', '/tmp/python-patch.tar.gz'])
+45 -70
View File
@@ -8,89 +8,71 @@ try:
except ImportError: except ImportError:
from pipes import quote as shlex_quote from pipes import quote as shlex_quote
try:
from urllib.request import urlopen
except ImportError:
from urllib2 import urlopen
from .util import prepare_command, get_build_verbosity_extra_flags from .util import prepare_command, get_build_verbosity_extra_flags
IS_RUNNING_ON_AZURE = os.path.exists('C:\\hostedtoolcache') IS_RUNNING_ON_AZURE = os.path.exists('C:\\hostedtoolcache')
IS_RUNNING_ON_TRAVIS = os.environ.get('TRAVIS_OS_NAME') == 'windows' IS_RUNNING_ON_TRAVIS = os.environ.get('TRAVIS_OS_NAME') == 'windows'
def get_python_path(config): def get_python_path(config):
if IS_RUNNING_ON_AZURE: nuget_args = get_nuget_args(config)
# We can't hard-code the paths because on Azure, we don't know which return os.path.join(nuget_args[-1], nuget_args[0] + "." + config.version, "tools")
# bugfix release of Python we are getting so we need to check which
# ones exist. We just use the first one that is found since there should
# only be one.
path_pattern = 'C:\\hostedtoolcache\\windows\\Python\\{version}\\{arch}'.format(
version=config.version.replace('x', '*'),
arch='x86' if config.arch == '32' else 'x64'
)
try:
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]
return 'C:\\Python{major}{minor}{arch}'.format(
major=major,
minor=minor,
arch = '-x64' if config.arch == '64' else ''
)
def get_nuget_args(configuration): def get_nuget_args(configuration):
if configuration.nuget_version is None:
return None
python_name = "python" if configuration.version[0] == '3' else "python2" python_name = "python" if configuration.version[0] == '3' else "python2"
if configuration.arch == "32": if configuration.arch == "32":
python_name = python_name + "x86" python_name = python_name + "x86"
return [python_name, "-Version", configuration.nuget_version, "-OutputDirectory", "C:/python"] return [python_name, "-Version", configuration.version, "-OutputDirectory", "C:/python"]
def get_python_configurations(build_selector): def get_python_configurations(build_selector):
PythonConfiguration = namedtuple('PythonConfiguration', ['version', 'arch', 'identifier', 'path', "nuget_version"]) PythonConfiguration = namedtuple('PythonConfiguration', ['version', 'arch', 'identifier'])
python_configurations = [ python_configurations = [
PythonConfiguration(version='2.7.x', arch="32", identifier='cp27-win32', path='C:\\Python27', nuget_version="2.7.16"), PythonConfiguration(version='2.7.17', arch="32", identifier='cp27-win32'),
PythonConfiguration(version='2.7.x', arch="64", identifier='cp27-win_amd64', path='C:\\Python27-x64', nuget_version="2.7.16"), PythonConfiguration(version='2.7.17', arch="64", identifier='cp27-win_amd64'),
PythonConfiguration(version='3.4.x', arch="32", identifier='cp34-win32', path='C:\\Python34', nuget_version=None), PythonConfiguration(version='3.5.4', arch="32", identifier='cp35-win32'),
PythonConfiguration(version='3.4.x', arch="64", identifier='cp34-win_amd64', path='C:\\Python34-x64', nuget_version=None), PythonConfiguration(version='3.5.4', arch="64", identifier='cp35-win_amd64'),
PythonConfiguration(version='3.5.x', arch="32", identifier='cp35-win32', path='C:\\Python35', nuget_version="3.5.4"), PythonConfiguration(version='3.6.8', arch="32", identifier='cp36-win32'),
PythonConfiguration(version='3.5.x', arch="64", identifier='cp35-win_amd64', path='C:\\Python35-x64', nuget_version="3.5.4"), PythonConfiguration(version='3.6.8', arch="64", identifier='cp36-win_amd64'),
PythonConfiguration(version='3.6.x', arch="32", identifier='cp36-win32', path='C:\\Python36', nuget_version="3.6.8"), PythonConfiguration(version='3.7.5', arch="32", identifier='cp37-win32'),
PythonConfiguration(version='3.6.x', arch="64", identifier='cp36-win_amd64', path='C:\\Python36-x64', nuget_version="3.6.8"), PythonConfiguration(version='3.7.5', arch="64", identifier='cp37-win_amd64'),
PythonConfiguration(version='3.7.x', arch="32", identifier='cp37-win32', path='C:\\Python37', nuget_version="3.7.4"), PythonConfiguration(version='3.8.0', arch="32", identifier='cp38-win32'),
PythonConfiguration(version='3.7.x', arch="64", identifier='cp37-win_amd64', path='C:\\Python37-x64', nuget_version="3.7.4") PythonConfiguration(version='3.8.0', arch="64", identifier='cp38-win_amd64'),
] ]
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: if IS_RUNNING_ON_TRAVIS:
# cannot install VCForPython27.msi which is needed for compiling C software # cannot install VCForPython27.msi which is needed for compiling C software
# try with (and similar): msiexec /i VCForPython27.msi ALLUSERS=1 ACCEPT=YES /passive # 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 not c.version.startswith('2.7.')]
python_configurations = [c for c in python_configurations if c.version != '2.7.x' and c.version != '3.4.x']
# skip builds as required # skip builds as required
python_configurations = [c for c in python_configurations if build_selector(c.identifier)] python_configurations = [c for c in python_configurations if build_selector(c.identifier)]
return python_configurations return python_configurations
def build(project_dir, output_dir, test_command, test_requires, test_extras, before_build, build_verbosity, build_selector, environment): def build(project_dir, output_dir, test_command, test_requires, test_extras, before_build, build_verbosity, build_selector, environment):
def simple_shell(args, env=None, cwd=None):
print('+ ' + ' '.join(args))
args = ['cmd', '/E:ON', '/V:ON', '/C'] + args
return subprocess.check_call(' '.join(args), env=env, cwd=cwd)
def download(url, dest):
print('+ Download ' + url + ' to ' + dest)
response = urlopen(url)
try:
with open(dest, 'wb') as file:
file.write(response.read())
finally:
response.close()
if IS_RUNNING_ON_AZURE or IS_RUNNING_ON_TRAVIS: if IS_RUNNING_ON_AZURE or IS_RUNNING_ON_TRAVIS:
def shell(args, env=None, cwd=None): shell = simple_shell
print('+ ' + ' '.join(args))
args = ['cmd', '/E:ON', '/V:ON', '/C'] + args
return subprocess.check_call(' '.join(args), env=env, cwd=cwd)
else: else:
run_with_env = os.path.abspath(os.path.join(os.path.dirname(__file__), 'resources', 'appveyor_run_with_env.cmd')) run_with_env = os.path.abspath(os.path.join(os.path.dirname(__file__), 'resources', 'appveyor_run_with_env.cmd'))
@@ -106,21 +88,19 @@ def build(project_dir, output_dir, test_command, test_requires, test_extras, bef
temp_dir = tempfile.mkdtemp(prefix='cibuildwheel') temp_dir = tempfile.mkdtemp(prefix='cibuildwheel')
built_wheel_dir = os.path.join(temp_dir, 'built_wheel') built_wheel_dir = os.path.join(temp_dir, 'built_wheel')
if IS_RUNNING_ON_TRAVIS: # install nuget as best way to provide python
# instal nuget as best way for provide python nuget = 'C:\\nuget.exe'
shell(["choco", "install", "nuget.commandline"]) download('https://dist.nuget.org/win-x86-commandline/latest/nuget.exe', nuget)
# get pip fo this installation which not have. # 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'
get_pip_script = 'C:\\get-pip.py' download('https://bootstrap.pypa.io/get-pip.py', get_pip_script)
shell(['curl', '-L', '-o', get_pip_script, get_pip_url])
python_configurations = get_python_configurations(build_selector) python_configurations = get_python_configurations(build_selector)
for config in python_configurations: for config in python_configurations:
config_python_path = get_python_path(config) 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): simple_shell([nuget, "install"] + get_nuget_args(config))
shell(["nuget", "install"] + get_nuget_args(config)) if not os.path.exists(os.path.join(config_python_path, 'Scripts', 'pip.exe')):
if not os.path.exists(os.path.join(config_python_path, 'Scripts', 'pip.exe')): simple_shell([os.path.join(config_python_path, 'python.exe'), get_pip_script ])
shell([os.path.join(config_python_path, 'python.exe'), get_pip_script ])
# check python & pip exist for this configuration # check python & pip exist for this configuration
assert os.path.exists(os.path.join(config_python_path, 'python.exe')) assert os.path.exists(os.path.join(config_python_path, 'python.exe'))
@@ -147,12 +127,7 @@ 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) shell(['python', '-c', '"import struct; print(struct.calcsize(\'P\') * 8)\"'], env=env)
# prepare the Python environment # prepare the Python environment
if config.version == "3.4.x": shell(['python', '-m', 'pip', 'install', '--upgrade', 'pip'], env=env)
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', '--upgrade', 'setuptools'], env=env)
shell(['pip', 'install', 'wheel'], env=env) shell(['pip', 'install', 'wheel'], env=env)
+15 -14
View File
@@ -59,15 +59,15 @@ For `linux` you need Docker running, on Mac or Linux. For `macos`, you need a Ma
> Choose the Python versions to build > Choose the Python versions to build
Space-separated list of builds to build and skip. Each build has an identifier like `cp27-manylinux_x86_64` or `cp34-macosx_10_6_intel` - you can list specific ones to build and `cibuildwheel` will only build those, and/or list ones to skip and `cibuildwheel` won't try to build them. Space-separated list of builds to build and skip. Each build has an identifier like `cp27-manylinux_x86_64` or `cp35-macosx_10_6_intel` - you can list specific ones to build and `cibuildwheel` will only build those, and/or list ones to skip and `cibuildwheel` won't try to build them.
When both options are specified, both conditions are applied and only builds with a tag that matches `CIBW_BUILD` and does not match `CIBW_SKIP` will be built. When both options are specified, both conditions are applied and only builds with a tag that matches `CIBW_BUILD` and does not match `CIBW_SKIP` will be built.
The format is `python_tag-platform_tag`. The tags are similar but not identical to the ones defined in [PEP 425](https://www.python.org/dev/peps/pep-0425/#details). The format is `python_tag-platform_tag`. The tags are similar but not identical to the ones defined in [PEP 425](https://www.python.org/dev/peps/pep-0425/#details).
Python tags look like `cp27` `cp34` `cp35` `cp36` `cp37` Python tags look like `cp27` `cp34` `cp35` `cp36` `cp37` `cp38`
Platform tags look like `macosx_10_6_intel` `manylinux_x86_64` `manylinux_i686` `win32` `win_amd64` Platform tags look like `macosx_10_6_intel` `macosx_10_9_x86_64` `manylinux_x86_64` `manylinux_i686` `win32` `win_amd64`
You can also use shell-style globbing syntax (as per `fnmatch`). You can also use shell-style globbing syntax (as per `fnmatch`).
@@ -77,10 +77,11 @@ Examples:
- Only build on Python 3.6: `CIBW_BUILD=cp36-*` - Only build on Python 3.6: `CIBW_BUILD=cp36-*`
- Skip building on Python 2.7 on the Mac: `CIBW_SKIP=cp27-macosx_10_6_intel` - Skip building on Python 2.7 on the Mac: `CIBW_SKIP=cp27-macosx_10_6_intel`
- Skip building on Python 3.8 on the Mac: `CIBW_SKIP=cp38-macosx_10_9_x86_64`
- Skip building on Python 2.7 on all platforms: `CIBW_SKIP=cp27-*` - Skip building on Python 2.7 on all platforms: `CIBW_SKIP=cp27-*`
- Skip Python 2.7 on Windows: `CIBW_SKIP=cp27-win*` - Skip Python 2.7 on Windows: `CIBW_SKIP=cp27-win*`
- Skip Python 2.7 on 32-bit Windows: `CIBW_SKIP=cp27-win32` - Skip Python 2.7 on 32-bit Windows: `CIBW_SKIP=cp27-win32`
- Skip Python 3.4 and Python 3.5: `CIBW_SKIP=cp34-* cp35-*` - Skip Python 2.7 and Python 3.5: `CIBW_SKIP=cp27-* cp35-*`
- Skip Python 3.6 on Linux: `CIBW_SKIP=cp36-manylinux*` - Skip Python 3.6 on Linux: `CIBW_SKIP=cp36-manylinux*`
- Only build on Python 3 and skip 32-bit builds: `CIBW_BUILD=cp3?-*` and `CIBW_SKIP=*-win32 *-manylinux_i686` - Only build on Python 3 and skip 32-bit builds: `CIBW_BUILD=cp3?-*` and `CIBW_SKIP=*-win32 *-manylinux_i686`
@@ -95,10 +96,10 @@ You must set this variable to pass variables to Linux builds (since they execute
You can use `$PATH` syntax to insert other variables, or the `$(pwd)` syntax to insert the output of other shell commands. You can use `$PATH` syntax to insert other variables, or the `$(pwd)` syntax to insert the output of other shell commands.
Example: `CFLAGS="-g -Wall" CXXFLAGS="-Wall"` Example: `CFLAGS="-g -Wall" CXXFLAGS="-Wall"`\
Example: `PATH=$PATH:/usr/local/bin` Example: `PATH=$PATH:/usr/local/bin`\
Example: `BUILD_TIME="$(date)"` Example: `BUILD_TIME="$(date)"`\
Example: `PIP_EXTRA_INDEX_URL="https://pypi.myorg.com/simple"` Example: `PIP_EXTRA_INDEX_URL="https://pypi.myorg.com/simple"`
Platform-specific variants also available: Platform-specific variants also available:
`CIBW_ENVIRONMENT_MACOS` | `CIBW_ENVIRONMENT_WINDOWS` | `CIBW_ENVIRONMENT_LINUX` `CIBW_ENVIRONMENT_MACOS` | `CIBW_ENVIRONMENT_WINDOWS` | `CIBW_ENVIRONMENT_LINUX`
@@ -114,11 +115,11 @@ If dependencies are required to build your wheel (for example if you include a h
The active Python binary can be accessed using `python`, and pip with `pip`; `cibuildwheel` makes sure the right version of Python and pip will be executed. `{project}` can be used as a placeholder for the absolute path to the project's root. The active Python binary can be accessed using `python`, and pip with `pip`; `cibuildwheel` makes sure the right version of Python and pip will be executed. `{project}` can be used as a placeholder for the absolute path to the project's root.
Example: `pip install .` Example: `pip install .`\
Example: `pip install pybind11` Example: `pip install pybind11`\
Example: `yum install -y libffi-dev && pip install .` Example: `yum install -y libffi-dev && pip install .`
Platform-specific variants also available: Platform-specific variants also available:\
`CIBW_BEFORE_BUILD_MACOS` | `CIBW_BEFORE_BUILD_WINDOWS` | `CIBW_BEFORE_BUILD_LINUX` `CIBW_BEFORE_BUILD_MACOS` | `CIBW_BEFORE_BUILD_WINDOWS` | `CIBW_BEFORE_BUILD_LINUX`
### CIBW_MANYLINUX_X86_64_IMAGE, CIBW_MANYLINUX_I686_IMAGE {: #manylinux-image} ### CIBW_MANYLINUX_X86_64_IMAGE, CIBW_MANYLINUX_I686_IMAGE {: #manylinux-image}
@@ -132,8 +133,8 @@ Beware to specify a valid Docker image that can be used in the same way as the o
Note that `auditwheel` detects the version of the `manylinux` standard in the Docker image through the `AUDITWHEEL_PLAT` environment variable, as `cibuildwheel` has no way of detecting the correct `--plat` command line argument to pass to `auditwheel` for a custom image. If a Docker image does not correctly set this `AUDITWHEEL_PLAT` environment variable, the `CIBW_ENVIRONMENT` option can be used to do so (e.g., `CIBW_ENVIRONMENT="manylinux2010_$(uname -m)"`). Note that `auditwheel` detects the version of the `manylinux` standard in the Docker image through the `AUDITWHEEL_PLAT` environment variable, as `cibuildwheel` has no way of detecting the correct `--plat` command line argument to pass to `auditwheel` for a custom image. If a Docker image does not correctly set this `AUDITWHEEL_PLAT` environment variable, the `CIBW_ENVIRONMENT` option can be used to do so (e.g., `CIBW_ENVIRONMENT="manylinux2010_$(uname -m)"`).
Example: `manylinux1` Example: `manylinux1`\
Example: `dockcross/manylinux-x64` Example: `dockcross/manylinux-x64`\
Example: `dockcross/manylinux-x86` Example: `dockcross/manylinux-x86`
## Testing ## Testing
@@ -155,7 +156,7 @@ Platform-specific variants also available:
Space-separated list of dependencies required for running the tests. Space-separated list of dependencies required for running the tests.
Example: `pytest` Example: `pytest`\
Example: `nose==1.3.7 moto==0.4.31` Example: `nose==1.3.7 moto==0.4.31`
Platform-specific variants also available: Platform-specific variants also available:
+3 -10
View File
@@ -28,14 +28,7 @@ jobs:
- job: windows - job: windows
pool: {vmImage: 'vs2017-win2016'} pool: {vmImage: 'vs2017-win2016'}
steps: steps:
- {task: UsePythonVersion@0, inputs: {versionSpec: '2.7', architecture: x86}} - task: UsePythonVersion@0
- {task: UsePythonVersion@0, inputs: {versionSpec: '2.7', architecture: x64}}
- {task: UsePythonVersion@0, inputs: {versionSpec: '3.5', architecture: x86}}
- {task: UsePythonVersion@0, inputs: {versionSpec: '3.5', architecture: x64}}
- {task: UsePythonVersion@0, inputs: {versionSpec: '3.6', architecture: x86}}
- {task: UsePythonVersion@0, inputs: {versionSpec: '3.6', architecture: x64}}
- {task: UsePythonVersion@0, inputs: {versionSpec: '3.7', architecture: x86}}
- {task: UsePythonVersion@0, inputs: {versionSpec: '3.7', architecture: x64}}
- script: choco install vcpython27 -f -y - script: choco install vcpython27 -f -y
displayName: Install Visual C++ for Python 2.7 displayName: Install Visual C++ for Python 2.7
- bash: | - bash: |
@@ -73,7 +66,7 @@ script:
- cibuildwheel --output-dir wheelhouse - cibuildwheel --output-dir wheelhouse
``` ```
To build on Windows too, add this matrix entry: To build on Windows too, add this matrix entry:
```yaml ```yaml
- os: windows - os: windows
language: shell language: shell
@@ -90,7 +83,7 @@ Commit this file, enable building of your repo on Travis CI, and push.
Then setup a deployment method by following the [Travis CI deployment docs](https://docs.travis-ci.com/user/deployment/), or see [Delivering to PyPI](deliver-to-pypi.md). For more info on `.travis.yml`, check out the [docs](https://docs.travis-ci.com/). Then setup a deployment method by following the [Travis CI deployment docs](https://docs.travis-ci.com/user/deployment/), or see [Delivering to PyPI](deliver-to-pypi.md). For more info on `.travis.yml`, check out the [docs](https://docs.travis-ci.com/).
## CircleCI [linux/mac] ## CircleCI [linux/mac]
To build Linux and Mac wheels on CircleCI, create a `.circleci/config.yml` file in your repo, To build Linux and Mac wheels on CircleCI, create a `.circleci/config.yml` file in your repo,
> .circleci/config.yml > .circleci/config.yml
+2
View File
@@ -21,6 +21,8 @@ setup(
package_data={ package_data={
'cibuildwheel': ['resources/*'], 'cibuildwheel': ['resources/*'],
}, },
# Supported python versions
python_requires='>=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*',
keywords='ci wheel packaging pypi travis appveyor macos linux windows', keywords='ci wheel packaging pypi travis appveyor macos linux windows',
classifiers=[ classifiers=[
'Intended Audience :: Developers', 'Intended Audience :: Developers',
+3 -3
View File
@@ -7,11 +7,11 @@ def test():
# build the wheels # build the wheels
utils.cibuildwheel_run(project_dir, add_env={ utils.cibuildwheel_run(project_dir, add_env={
'CIBW_BUILD': 'cp3?-*', 'CIBW_BUILD': 'cp3?-*',
'CIBW_SKIP': 'cp34-*', 'CIBW_SKIP': 'cp37-*',
}) })
# check that we got the right wheels. There should be no 2.7 or 3.4. # check that we got the right wheels. There should be no 2.7 or 3.7.
expected_wheels = [w for w in utils.expected_wheels('spam', '0.1.0') expected_wheels = [w for w in utils.expected_wheels('spam', '0.1.0')
if ('-cp3' in w) and ('-cp34' not in w)] if ('-cp3' in w) and ('-cp37' not in w)]
actual_wheels = os.listdir('wheelhouse') actual_wheels = os.listdir('wheelhouse')
assert set(actual_wheels) == set(expected_wheels) assert set(actual_wheels) == set(expected_wheels)
+14 -17
View File
@@ -26,14 +26,14 @@ def cibuildwheel_get_build_identifiers(project_path, env=None):
def cibuildwheel_run(project_path, env=None, add_env=None): def cibuildwheel_run(project_path, env=None, add_env=None):
''' '''
Runs cibuildwheel as a subprocess, building the project at project_path. Runs cibuildwheel as a subprocess, building the project at project_path.
Uses the current Python interpreter. Uses the current Python interpreter.
Configure settings using env. Configure settings using env.
''' '''
if env is None: if env is None:
env = os.environ.copy() env = os.environ.copy()
if add_env is not None: if add_env is not None:
env.update(add_env) env.update(add_env)
@@ -51,60 +51,57 @@ def expected_wheels(package_name, package_version):
templates = [ templates = [
'{package_name}-{package_version}-cp27-cp27m-manylinux1_x86_64.whl', '{package_name}-{package_version}-cp27-cp27m-manylinux1_x86_64.whl',
'{package_name}-{package_version}-cp27-cp27mu-manylinux1_x86_64.whl', '{package_name}-{package_version}-cp27-cp27mu-manylinux1_x86_64.whl',
'{package_name}-{package_version}-cp34-cp34m-manylinux1_x86_64.whl',
'{package_name}-{package_version}-cp35-cp35m-manylinux1_x86_64.whl', '{package_name}-{package_version}-cp35-cp35m-manylinux1_x86_64.whl',
'{package_name}-{package_version}-cp36-cp36m-manylinux1_x86_64.whl', '{package_name}-{package_version}-cp36-cp36m-manylinux1_x86_64.whl',
'{package_name}-{package_version}-cp37-cp37m-manylinux1_x86_64.whl', '{package_name}-{package_version}-cp37-cp37m-manylinux1_x86_64.whl',
'{package_name}-{package_version}-cp38-cp38-manylinux1_x86_64.whl',
'{package_name}-{package_version}-cp27-cp27m-manylinux2010_x86_64.whl', '{package_name}-{package_version}-cp27-cp27m-manylinux2010_x86_64.whl',
'{package_name}-{package_version}-cp27-cp27mu-manylinux2010_x86_64.whl', '{package_name}-{package_version}-cp27-cp27mu-manylinux2010_x86_64.whl',
'{package_name}-{package_version}-cp34-cp34m-manylinux2010_x86_64.whl',
'{package_name}-{package_version}-cp35-cp35m-manylinux2010_x86_64.whl', '{package_name}-{package_version}-cp35-cp35m-manylinux2010_x86_64.whl',
'{package_name}-{package_version}-cp36-cp36m-manylinux2010_x86_64.whl', '{package_name}-{package_version}-cp36-cp36m-manylinux2010_x86_64.whl',
'{package_name}-{package_version}-cp37-cp37m-manylinux2010_x86_64.whl', '{package_name}-{package_version}-cp37-cp37m-manylinux2010_x86_64.whl',
'{package_name}-{package_version}-cp38-cp38-manylinux2010_x86_64.whl',
'{package_name}-{package_version}-cp27-cp27m-manylinux1_i686.whl', '{package_name}-{package_version}-cp27-cp27m-manylinux1_i686.whl',
'{package_name}-{package_version}-cp27-cp27mu-manylinux1_i686.whl', '{package_name}-{package_version}-cp27-cp27mu-manylinux1_i686.whl',
'{package_name}-{package_version}-cp34-cp34m-manylinux1_i686.whl',
'{package_name}-{package_version}-cp35-cp35m-manylinux1_i686.whl', '{package_name}-{package_version}-cp35-cp35m-manylinux1_i686.whl',
'{package_name}-{package_version}-cp36-cp36m-manylinux1_i686.whl', '{package_name}-{package_version}-cp36-cp36m-manylinux1_i686.whl',
'{package_name}-{package_version}-cp37-cp37m-manylinux1_i686.whl', '{package_name}-{package_version}-cp37-cp37m-manylinux1_i686.whl',
'{package_name}-{package_version}-cp38-cp38-manylinux1_i686.whl',
'{package_name}-{package_version}-cp27-cp27m-manylinux2010_i686.whl', '{package_name}-{package_version}-cp27-cp27m-manylinux2010_i686.whl',
'{package_name}-{package_version}-cp27-cp27mu-manylinux2010_i686.whl', '{package_name}-{package_version}-cp27-cp27mu-manylinux2010_i686.whl',
'{package_name}-{package_version}-cp34-cp34m-manylinux2010_i686.whl',
'{package_name}-{package_version}-cp35-cp35m-manylinux2010_i686.whl', '{package_name}-{package_version}-cp35-cp35m-manylinux2010_i686.whl',
'{package_name}-{package_version}-cp36-cp36m-manylinux2010_i686.whl', '{package_name}-{package_version}-cp36-cp36m-manylinux2010_i686.whl',
'{package_name}-{package_version}-cp37-cp37m-manylinux2010_i686.whl', '{package_name}-{package_version}-cp37-cp37m-manylinux2010_i686.whl',
'{package_name}-{package_version}-cp38-cp38-manylinux2010_i686.whl',
] ]
elif platform == 'windows': elif platform == 'windows':
templates = [ templates = [
'{package_name}-{package_version}-cp27-cp27m-win32.whl', '{package_name}-{package_version}-cp27-cp27m-win32.whl',
'{package_name}-{package_version}-cp34-cp34m-win32.whl',
'{package_name}-{package_version}-cp35-cp35m-win32.whl', '{package_name}-{package_version}-cp35-cp35m-win32.whl',
'{package_name}-{package_version}-cp36-cp36m-win32.whl', '{package_name}-{package_version}-cp36-cp36m-win32.whl',
'{package_name}-{package_version}-cp37-cp37m-win32.whl', '{package_name}-{package_version}-cp37-cp37m-win32.whl',
'{package_name}-{package_version}-cp38-cp38-win32.whl',
'{package_name}-{package_version}-cp27-cp27m-win_amd64.whl', '{package_name}-{package_version}-cp27-cp27m-win_amd64.whl',
'{package_name}-{package_version}-cp34-cp34m-win_amd64.whl',
'{package_name}-{package_version}-cp35-cp35m-win_amd64.whl', '{package_name}-{package_version}-cp35-cp35m-win_amd64.whl',
'{package_name}-{package_version}-cp36-cp36m-win_amd64.whl', '{package_name}-{package_version}-cp36-cp36m-win_amd64.whl',
'{package_name}-{package_version}-cp37-cp37m-win_amd64.whl', '{package_name}-{package_version}-cp37-cp37m-win_amd64.whl',
'{package_name}-{package_version}-cp38-cp38-win_amd64.whl',
] ]
elif platform == 'macos': elif platform == 'macos':
templates = [ templates = [
'{package_name}-{package_version}-cp27-cp27m-macosx_10_6_intel.whl', '{package_name}-{package_version}-cp27-cp27m-macosx_10_6_intel.whl',
'{package_name}-{package_version}-cp34-cp34m-macosx_10_6_intel.whl',
'{package_name}-{package_version}-cp35-cp35m-macosx_10_6_intel.whl', '{package_name}-{package_version}-cp35-cp35m-macosx_10_6_intel.whl',
'{package_name}-{package_version}-cp36-cp36m-macosx_10_6_intel.whl', '{package_name}-{package_version}-cp36-cp36m-macosx_10_6_intel.whl',
'{package_name}-{package_version}-cp37-cp37m-macosx_10_6_intel.whl', '{package_name}-{package_version}-cp37-cp37m-macosx_10_6_intel.whl',
'{package_name}-{package_version}-cp38-cp38-macosx_10_9_x86_64.whl',
] ]
else: else:
raise Exception('unsupported platform') raise Exception('unsupported platform')
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: if IS_WINDOWS_RUNNING_ON_TRAVIS:
# Python 2.7 and 3.4 isn't supported on Travis. # Python 2.7 isn't supported on Travis.
templates = [t for t in templates if '-cp27-' not in t and '-cp34-' not in t] templates = [t for t in templates if '-cp27-' not in t]
return [filename.format(package_name=package_name, package_version=package_version) return [filename.format(package_name=package_name, package_version=package_version)
for filename in templates] for filename in templates]
+6 -2
View File
@@ -1,3 +1,4 @@
import os
from cibuildwheel.environment import parse_environment from cibuildwheel.environment import parse_environment
@@ -37,12 +38,15 @@ def test_inheritance():
def test_shell_eval(): def test_shell_eval():
environment_recipe = parse_environment('VAR="$(echo "a test" string)"') environment_recipe = parse_environment('VAR="$(echo "a test" string)"')
env_copy = os.environ.copy()
env_copy.pop('VAR', None)
environment_dict = environment_recipe.as_dictionary( environment_dict = environment_recipe.as_dictionary(
prev_environment={} prev_environment=env_copy
) )
environment_cmds = environment_recipe.as_shell_commands() environment_cmds = environment_recipe.as_shell_commands()
assert environment_dict == {'VAR': 'a test string'} assert environment_dict['VAR'] == 'a test string'
assert environment_cmds == ['export VAR="$(echo "a test" string)"'] assert environment_cmds == ['export VAR="$(echo "a test" string)"']
def test_shell_eval_and_env(): def test_shell_eval_and_env():