From 513ef49cd43b4c4d80fcf11afa48cefde8deb784 Mon Sep 17 00:00:00 2001 From: mayeut Date: Tue, 19 Nov 2019 23:36:20 +0100 Subject: [PATCH 1/5] Only build x86_64 / Intel 10.9+ on macOS --- README.md | 14 +++++++------- cibuildwheel/__main__.py | 4 ++-- cibuildwheel/macos.py | 23 ++++++++++++++--------- docs/options.md | 20 ++++++++++---------- test/shared/utils.py | 14 ++++++-------- unit_test/main_options_test.py | 16 ++++++++-------- 6 files changed, 47 insertions(+), 44 deletions(-) diff --git a/README.md b/README.md index 38d8413c7..2989eac23 100644 --- a/README.md +++ b/README.md @@ -15,13 +15,13 @@ Python wheels are great. Building them across **Mac, Linux, Windows**, on **mult What does it do? ---------------- -| | macOS 10.6+ intel | macOS 10.9+ x86_64 | manylinux i686 | manylinux x86_64 | Windows 32bit | Windows 64bit | -|---|---|---|---|---|---|---| -| Python 2.7 | ✅ | | ✅ | ✅ | ✅¹ | ✅¹ | -| Python 3.5 | ✅ | | ✅ | ✅ | ✅ | ✅ | -| Python 3.6 | ✅ | | ✅ | ✅ | ✅ | ✅ | -| Python 3.7 | ✅ | | ✅ | ✅ | ✅ | ✅ | -| Python 3.8 | | ✅ | ✅ | ✅ | ✅ | ✅ | +| | macOS 10.9+ x86_64 | manylinux i686 | manylinux x86_64 | Windows 32bit | Windows 64bit | +|---|---|---|---|---|---| +| Python 2.7 | ✅ | ✅ | ✅ | ✅¹ | ✅¹ | +| Python 3.5 | ✅ | ✅ | ✅ | ✅ | ✅ | +| Python 3.6 | ✅ | ✅ | ✅ | ✅ | ✅ | +| Python 3.7 | ✅ | ✅ | ✅ | ✅ | ✅ | +| Python 3.8 | ✅ | ✅ | ✅ | ✅ | ✅ | > ¹ Not supported on Travis diff --git a/cibuildwheel/__main__.py b/cibuildwheel/__main__.py index 9b3db905e..e4a1b0163 100644 --- a/cibuildwheel/__main__.py +++ b/cibuildwheel/__main__.py @@ -61,7 +61,7 @@ def main(): args = parser.parse_args() detect_obsolete_options() - + if args.platform != 'auto': platform = args.platform else: @@ -97,7 +97,7 @@ def main(): if platform == 'linux': repair_command_default = 'auditwheel repair -w {dest_dir} {wheel}' elif platform == 'macos': - repair_command_default = 'delocate-listdeps {wheel} && delocate-wheel -w {dest_dir} {wheel}' + repair_command_default = 'delocate-listdeps {wheel} && delocate-wheel --require-archs x86_64 -w {dest_dir} {wheel}' else: repair_command_default = '' repair_command = get_option_from_environment('CIBW_REPAIR_WHEEL_COMMAND', platform=platform, default=repair_command_default) diff --git a/cibuildwheel/macos.py b/cibuildwheel/macos.py index d7a50d0c6..c137da8a6 100644 --- a/cibuildwheel/macos.py +++ b/cibuildwheel/macos.py @@ -14,11 +14,11 @@ def get_python_configurations(build_selector): PythonConfiguration = namedtuple('PythonConfiguration', ['version', 'identifier', 'url']) python_configurations = [ - PythonConfiguration(version='2.7', identifier='cp27-macosx_intel', url='https://www.python.org/ftp/python/2.7.17/python-2.7.17-macosx10.6.pkg'), - PythonConfiguration(version='3.5', identifier='cp35-macosx_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_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_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_x86_64', url='https://www.python.org/ftp/python/3.8.0/python-3.8.0-macosx10.9.pkg'), + PythonConfiguration(version='2.7', identifier='cp27-macosx_x86_64', url='https://www.python.org/ftp/python/2.7.17/python-2.7.17-macosx10.9.pkg'), + PythonConfiguration(version='3.5', identifier='cp35-macosx_x86_64', url='https://www.python.org/ftp/python/3.5.4/python-3.5.4-macosx10.6.pkg'), + PythonConfiguration(version='3.6', identifier='cp36-macosx_x86_64', url='https://www.python.org/ftp/python/3.6.8/python-3.6.8-macosx10.9.pkg'), + PythonConfiguration(version='3.7', identifier='cp37-macosx_x86_64', url='https://www.python.org/ftp/python/3.7.6/python-3.7.6-macosx10.9.pkg'), + PythonConfiguration(version='3.8', identifier='cp38-macosx_x86_64', url='https://www.python.org/ftp/python/3.8.1/python-3.8.1-macosx10.9.pkg'), ] # skip builds as required @@ -32,6 +32,7 @@ def build(project_dir, output_dir, test_command, test_requires, test_extras, bef repaired_wheel_dir = os.path.join(temp_dir, 'repaired_wheel') python_configurations = get_python_configurations(build_selector) + get_pip_url = 'https://bootstrap.pypa.io/get-pip.py' get_pip_script = '/tmp/get-pip.py' @@ -50,20 +51,19 @@ def call(args, env=None, cwd=None, shell=False): return subprocess.check_call(args, env=env, cwd=cwd, shell=shell) # get latest pip once and for all - - call(['curl', '-L', '--retry', '3', '--retry-delay', '3', '-o', get_pip_script, get_pip_url]) + call(['curl', '--retry', '3', '--retry-delay', '3', '-sSLo', get_pip_script, get_pip_url]) for config in python_configurations: # if this version of python isn't installed, get it from python.org and install python_package_identifier = 'org.python.Python.PythonFramework-%s' % config.version if python_package_identifier not in installed_system_packages: # download the pkg - call(['curl', '-L', '-o', '/tmp/Python.pkg', config.url]) + call(['curl', '--retry', '3', '--retry-delay', '3', '-sSLo', '/tmp/Python.pkg', config.url]) # install call(['sudo', 'installer', '-pkg', '/tmp/Python.pkg', '-target', '/']) # patch open ssl 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', '--retry', '3', '--retry-delay', '3', '-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']) installation_bin_path = '/Library/Frameworks/Python.framework/Versions/{}/bin'.format(config.version) @@ -98,6 +98,11 @@ def call(args, env=None, cwd=None, shell=False): call(['pip', '--version'], env=env) call(['pip', 'install', '--upgrade', 'setuptools', 'wheel', 'delocate'], env=env) + # setup target platform, only required for python 3.5 + if config.version == '3.5': + env['_PYTHON_HOST_PLATFORM'] = 'macosx-10.9-x86_64' # cross-compilation platform override + env['ARCHFLAGS'] = '-arch x86_64' # https://github.com/python/cpython/blob/a5ed2fe0eedefa1649aa93ee74a0bafc8e628a10/Lib/_osx_support.py#L260 + # run the before_build command if before_build: before_build_prepared = prepare_command(before_build, project=abs_project_dir) diff --git a/docs/options.md b/docs/options.md index 524335869..82c1f4351 100644 --- a/docs/options.md +++ b/docs/options.md @@ -64,7 +64,7 @@ This option can also be set using the command-line option `--platform`. > 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 `cp35-macosx_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_x86_64` - 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. @@ -72,13 +72,13 @@ When setting the options, you can use shell-style globbing syntax (as per `fnmat
-| | macOS 64bit | macOS 32/64bit | Manylinux 64bit | Manylinux 32bit | Windows 64bit | Windows 32bit | -|------------|---------------------|--------------------|------------------------|----------------------|-----------------|----------------| -| Python 2.7 | | cp27-macosx_intel | cp27-manylinux_x86_64 | cp27-manylinux_i686 | cp27-win_amd64 | cp27-win32 | -| Python 3.5 | | cp35-macosx_intel | cp35-manylinux_x86_64 | cp35-manylinux_i686 | cp35-win_amd64 | cp35-win32 | -| Python 3.6 | | cp36-macosx_intel | cp36-manylinux_x86_64 | cp36-manylinux_i686 | cp36-win_amd64 | cp36-win32 | -| Python 3.7 | | cp37-macosx_intel | cp37-manylinux_x86_64 | cp37-manylinux_i686 | cp37-win_amd64 | cp37-win32 | -| Python 3.8 | cp38-macosx_x86_64 | | cp38-manylinux_x86_64 | cp38-manylinux_i686 | cp38-win_amd64 | cp38-win32 | +| | macOS 64bit | Manylinux 64bit | Manylinux 32bit | Windows 64bit | Windows 32bit | +|------------|--------------------|------------------------|----------------------|-----------------|----------------| +| Python 2.7 | cp27-macosx_x86_64 | cp27-manylinux_x86_64 | cp27-manylinux_i686 | cp27-win_amd64 | cp27-win32 | +| Python 3.5 | cp35-macosx_x86_64 | cp35-manylinux_x86_64 | cp35-manylinux_i686 | cp35-win_amd64 | cp35-win32 | +| Python 3.6 | cp36-macosx_x86_64 | cp36-manylinux_x86_64 | cp36-manylinux_i686 | cp36-win_amd64 | cp36-win32 | +| Python 3.7 | cp37-macosx_x86_64 | cp37-manylinux_x86_64 | cp37-manylinux_i686 | cp37-win_amd64 | cp37-win32 | +| Python 3.8 | cp38-macosx_x86_64 | cp38-manylinux_x86_64 | cp38-manylinux_i686 | cp38-win_amd64 | cp38-win32 | The list of supported and currently selected build identifiers can also be retrieved by passing the `--print-build-identifiers` flag to `cibuildwheel`. The format is `python_tag-platform_tag`, with tags similar to those in [PEP 425](https://www.python.org/dev/peps/pep-0425/#details). @@ -90,7 +90,7 @@ The format is `python_tag-platform_tag`, with tags similar to those in [PEP 425] CIBW_BUILD: cp36-* # Skip building on Python 2.7 on the Mac -CIBW_SKIP: cp27-macosx_intel +CIBW_SKIP: cp27-macosx_x86_64 # Skip building on Python 3.8 on the Mac CIBW_SKIP: cp38-macosx_x86_64 @@ -208,7 +208,7 @@ CIBW_BEFORE_BUILD: yum install -y libffi-dev && pip install . Default: - on Linux: `'auditwheel repair -w {dest_dir} {wheel}'` -- on macOS: `'delocate-listdeps {wheel} && delocate-wheel -w {dest_dir} {wheel}'` +- on macOS: `'delocate-listdeps {wheel} && delocate-wheel --require-archs x86_64 -w {dest_dir} {wheel}'` - on Windows: `''` A shell command to repair a built wheel by copying external library dependencies into the wheel tree and relinking them. diff --git a/test/shared/utils.py b/test/shared/utils.py index 9ed730ff9..099233269 100644 --- a/test/shared/utils.py +++ b/test/shared/utils.py @@ -86,22 +86,20 @@ def expected_wheels(package_name, package_version, manylinux_versions=['manylinu platform_tags.append('{manylinux_version}_{architecture}'.format( manylinux_version=manylinux_version, architecture=architecture )) - + def get_platform_tags(python_abi_tag): return platform_tags - + elif platform == 'windows': def get_platform_tags(python_abi_tag): return ['win32', 'win_amd64'] - + elif platform == 'macos': - + def get_platform_tags(python_abi_tag): - if python_abi_tag == 'cp38-cp38': - return ['macosx_' + (macosx_deployment_target or "10.9").replace(".", "_") + '_x86_64'] - else: - return ['macosx_' + (macosx_deployment_target or "10.6").replace(".", "_") + '_intel'] + return ['macosx_' + (macosx_deployment_target or "10.9").replace(".", "_") + '_x86_64'] + else: raise Exception('unsupported platform') diff --git a/unit_test/main_options_test.py b/unit_test/main_options_test.py index 90935fe8e..ece86fce7 100644 --- a/unit_test/main_options_test.py +++ b/unit_test/main_options_test.py @@ -50,7 +50,7 @@ def test_build_selector(platform, intercepted_build_args, monkeypatch): monkeypatch.setenv('CIBW_SKIP', SKIP) main() - + intercepted_build_selector = intercepted_build_args.kwargs['build_selector'] assert isinstance(intercepted_build_selector, BuildSelector) assert intercepted_build_selector('build-this') @@ -60,12 +60,12 @@ def test_build_selector(platform, intercepted_build_args, monkeypatch): @pytest.mark.parametrize('architecture, image, full_image', [ - ('x86_64', None, 'quay.io/pypa/manylinux2010_x86_64'), + ('x86_64', None, 'quay.io/pypa/manylinux2010_x86_64'), ('x86_64', 'manylinux1', 'quay.io/pypa/manylinux1_x86_64'), ('x86_64', 'manylinux2010', 'quay.io/pypa/manylinux2010_x86_64'), ('x86_64', 'manylinux2014', 'quay.io/pypa/manylinux2014_x86_64'), ('x86_64', 'custom_image', 'custom_image'), - ('i686', None, 'quay.io/pypa/manylinux2010_i686'), + ('i686', None, 'quay.io/pypa/manylinux2010_i686'), ('i686', 'manylinux1', 'quay.io/pypa/manylinux1_i686'), ('i686', 'manylinux2010', 'quay.io/pypa/manylinux2010_i686'), ('i686', 'manylinux2014', 'quay.io/pypa/manylinux2014_i686'), @@ -87,7 +87,7 @@ def get_default_repair_command(platform): if platform == 'linux': return 'auditwheel repair -w {dest_dir} {wheel}' elif platform == 'macos': - return 'delocate-listdeps {wheel} && delocate-wheel -w {dest_dir} {wheel}' + return 'delocate-listdeps {wheel} && delocate-wheel --require-archs x86_64 -w {dest_dir} {wheel}' elif platform == 'windows': return '' else: @@ -139,9 +139,9 @@ def test_test_requires(test_requires, platform_specific, platform, intercepted_b monkeypatch.setenv('CIBW_TEST_REQUIRES', 'overwritten') else: monkeypatch.setenv('CIBW_TEST_REQUIRES', test_requires) - + main() - + assert intercepted_build_args.kwargs['test_requires'] == (test_requires or '').split() @@ -154,9 +154,9 @@ def test_test_extras(test_extras, platform_specific, platform, intercepted_build monkeypatch.setenv('CIBW_TEST_EXTRAS', 'overwritten') else: monkeypatch.setenv('CIBW_TEST_EXTRAS', test_extras) - + main() - + assert intercepted_build_args.kwargs['test_extras'] == ('[' + test_extras + ']' if test_extras else '') From 1a7d1d8cb1d9ef4a0119518144a1e4490edf4501 Mon Sep 17 00:00:00 2001 From: Joe Rickerby Date: Fri, 31 Jan 2020 17:05:32 +0000 Subject: [PATCH 2/5] Add MACOSX_DEPLOYMENT_TARGET flag and don't overwrite user-set env vars --- cibuildwheel/macos.py | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/cibuildwheel/macos.py b/cibuildwheel/macos.py index c137da8a6..e677d8134 100644 --- a/cibuildwheel/macos.py +++ b/cibuildwheel/macos.py @@ -100,8 +100,14 @@ def call(args, env=None, cwd=None, shell=False): # setup target platform, only required for python 3.5 if config.version == '3.5': - env['_PYTHON_HOST_PLATFORM'] = 'macosx-10.9-x86_64' # cross-compilation platform override - env['ARCHFLAGS'] = '-arch x86_64' # https://github.com/python/cpython/blob/a5ed2fe0eedefa1649aa93ee74a0bafc8e628a10/Lib/_osx_support.py#L260 + if '_PYTHON_HOST_PLATFORM' not in env: + # cross-compilation platform override + env['_PYTHON_HOST_PLATFORM'] = 'macosx-10.9-x86_64' + if 'ARCHFLAGS' not in env: + # https://github.com/python/cpython/blob/a5ed2fe0eedefa1649aa93ee74a0bafc8e628a10/Lib/_osx_support.py#L260 + env['ARCHFLAGS'] = '-arch x86_64' + if 'MACOSX_DEPLOYMENT_TARGET' not in env: + env['MACOSX_DEPLOYMENT_TARGET'] = '10.9' # run the before_build command if before_build: From a143ff2bfdf85063a173b77443b3560cf69eb8f3 Mon Sep 17 00:00:00 2001 From: Joe Rickerby Date: Fri, 31 Jan 2020 17:06:58 +0000 Subject: [PATCH 3/5] Use the internal download() function rather than curl --- cibuildwheel/macos.py | 9 +++++---- cibuildwheel/util.py | 31 +++++++++++++++++++++++++++++++ cibuildwheel/windows.py | 30 +----------------------------- 3 files changed, 37 insertions(+), 33 deletions(-) diff --git a/cibuildwheel/macos.py b/cibuildwheel/macos.py index e677d8134..7480990fb 100644 --- a/cibuildwheel/macos.py +++ b/cibuildwheel/macos.py @@ -8,7 +8,7 @@ except ImportError: from pipes import quote as shlex_quote -from .util import prepare_command, get_build_verbosity_extra_flags +from .util import prepare_command, get_build_verbosity_extra_flags, download def get_python_configurations(build_selector): @@ -51,19 +51,20 @@ def call(args, env=None, cwd=None, shell=False): return subprocess.check_call(args, env=env, cwd=cwd, shell=shell) # get latest pip once and for all - call(['curl', '--retry', '3', '--retry-delay', '3', '-sSLo', get_pip_script, get_pip_url]) + download(get_pip_url, get_pip_script) for config in python_configurations: # if this version of python isn't installed, get it from python.org and install python_package_identifier = 'org.python.Python.PythonFramework-%s' % config.version if python_package_identifier not in installed_system_packages: # download the pkg - call(['curl', '--retry', '3', '--retry-delay', '3', '-sSLo', '/tmp/Python.pkg', config.url]) + download(config.url, '/tmp/Python.pkg') # install call(['sudo', 'installer', '-pkg', '/tmp/Python.pkg', '-target', '/']) # patch open ssl if config.version == '3.5': - call(['curl', '--retry', '3', '--retry-delay', '3', '-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]) + open_ssl_patch_url = '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 + download(open_ssl_patch_url, '/tmp/python-patch.tar.gz') call(['sudo', 'tar', '-C', '/Library/Frameworks/Python.framework/Versions/%s/' % config.version, '-xmf', '/tmp/python-patch.tar.gz']) installation_bin_path = '/Library/Frameworks/Python.framework/Versions/{}/bin'.format(config.version) diff --git a/cibuildwheel/util.py b/cibuildwheel/util.py index ccbe57c0a..0aedbcac9 100644 --- a/cibuildwheel/util.py +++ b/cibuildwheel/util.py @@ -1,5 +1,12 @@ from fnmatch import fnmatch import warnings +import os +from time import sleep + +try: + from urllib.request import urlopen +except ImportError: + from urllib2 import urlopen def prepare_command(command, **kwargs): @@ -50,3 +57,27 @@ def writelines(self, datas): def __getattr__(self, attr): return getattr(self.stream, attr) + + +def download(url, dest): + print('+ Download ' + url + ' to ' + dest) + dest_dir = os.path.dirname(dest) + if not os.path.exists(dest_dir): + os.makedirs(dest_dir) + + repeat_num = 3 + for i in range(repeat_num): + try: + response = urlopen(url) + except: + if i == repeat_num - 1: + raise + sleep(3) + continue + break + + try: + with open(dest, 'wb') as file: + file.write(response.read()) + finally: + response.close() diff --git a/cibuildwheel/windows.py b/cibuildwheel/windows.py index c09239344..c50c98104 100644 --- a/cibuildwheel/windows.py +++ b/cibuildwheel/windows.py @@ -1,6 +1,5 @@ from __future__ import print_function import os, tempfile, subprocess, shutil, sys -from time import sleep from collections import namedtuple from glob import glob @@ -9,12 +8,7 @@ except ImportError: 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, download IS_RUNNING_ON_AZURE = os.path.exists('C:\\hostedtoolcache') @@ -64,28 +58,6 @@ def simple_shell(args, env=None, cwd=None): 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) - dest_dir = os.path.dirname(dest) - if not os.path.exists(dest_dir): - os.makedirs(dest_dir) - repeat_num = 3 - for i in range(repeat_num): - try: - response = urlopen(url) - except: - if i == repeat_num - 1: - raise - sleep(3) - continue - break - - try: - with open(dest, 'wb') as file: - file.write(response.read()) - finally: - response.close() - if IS_RUNNING_ON_AZURE or IS_RUNNING_ON_TRAVIS: shell = simple_shell else: From a97b6a13f1e4f9975e33d96eaafb3d84382dc912 Mon Sep 17 00:00:00 2001 From: Joe Rickerby Date: Fri, 31 Jan 2020 17:11:56 +0000 Subject: [PATCH 4/5] Fix test protection reference --- unit_test/main_util_fixtures.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/unit_test/main_util_fixtures.py b/unit_test/main_util_fixtures.py index 8bc80d874..3c993b352 100644 --- a/unit_test/main_util_fixtures.py +++ b/unit_test/main_util_fixtures.py @@ -4,7 +4,7 @@ import os import subprocess -from cibuildwheel import linux, macos, windows +from cibuildwheel import linux, macos, windows, util class ArgsInterceptor(object): @@ -26,7 +26,7 @@ def fail_on_call(*args, **kwargs): raise RuntimeError("This should never be called") monkeypatch.setattr(subprocess, 'Popen', fail_on_call) - monkeypatch.setattr(windows, 'urlopen', fail_on_call) + monkeypatch.setattr(util, 'download', fail_on_call) monkeypatch.setattr(windows, 'build', fail_on_call) monkeypatch.setattr(linux, 'build', fail_on_call) monkeypatch.setattr(macos, 'build', fail_on_call) From c3f628d03d91d2d082aec2cbe7fdba6390e2b353 Mon Sep 17 00:00:00 2001 From: Joe Rickerby Date: Sat, 1 Feb 2020 21:44:07 +0000 Subject: [PATCH 5/5] Add migration for build identifier change, and test for migration --- cibuildwheel/__main__.py | 21 ++++++++++++--------- unit_test/main_options_test.py | 23 +++++++++++++++++++++++ 2 files changed, 35 insertions(+), 9 deletions(-) diff --git a/cibuildwheel/__main__.py b/cibuildwheel/__main__.py index e4a1b0163..bdc34aaf4 100644 --- a/cibuildwheel/__main__.py +++ b/cibuildwheel/__main__.py @@ -198,15 +198,18 @@ def detect_obsolete_options(): print("Option '{}' is not empty. Please unset '{}'".format(alternative, deprecated)) exit(2) - # Check for 'manylinux1' in the 'CIBW_BUILD' and 'CIBW_SKIP' options - for deprecated in ['CIBW_BUILD', 'CIBW_SKIP']: - if deprecated in os.environ and 'manylinux1' in os.environ[deprecated]: - print("Build identifiers with 'manylinux1' have been deprecated. Replacing all occurences of 'manylinux1' by 'manylinux' in the option '{}'".format(deprecated)) - os.environ[deprecated] = os.environ[deprecated].replace('manylinux1', 'manylinux') - if deprecated in os.environ and ("macosx_10_6" in os.environ[deprecated] or "macosx_10_9" in os.environ[deprecated]): - print("Build identifiers with 'macosx_10_6' or 'macosx_10_9' have been deprecated. Replacing all occurences with 'macosx' in the option '{}'".format(deprecated)) - os.environ[deprecated] = os.environ[deprecated].replace('macosx_10_6', 'macosx').replace('macosx_10_9', 'macosx') - + # Check for deprecated identifiers in 'CIBW_BUILD' and 'CIBW_SKIP' options + for option in ['CIBW_BUILD', 'CIBW_SKIP']: + for deprecated, alternative in [('manylinux1', 'manylinux'), + ('macosx_10_6_intel', 'macosx_x86_64'), + ('macosx_10_9_x86_64', 'macosx_x86_64')]: + if option in os.environ and deprecated in os.environ[option]: + print("Build identifiers with '{deprecated}' have been deprecated. Replacing all occurences of '{deprecated}' with '{alternative}' in the option '{option}'".format( + deprecated=deprecated, + alternative=alternative, + option=option, + )) + os.environ[option] = os.environ[option].replace(deprecated, alternative) def print_preamble(platform, build_options): print(textwrap.dedent(''' diff --git a/unit_test/main_options_test.py b/unit_test/main_options_test.py index ece86fce7..44d92da8e 100644 --- a/unit_test/main_options_test.py +++ b/unit_test/main_options_test.py @@ -204,3 +204,26 @@ def test_build_verbosity(build_verbosity, platform_specific, platform, intercept expected_verbosity = max(-3, min(3, int(build_verbosity or 0))) assert intercepted_build_args.kwargs['build_verbosity'] == expected_verbosity + + +@pytest.mark.parametrize('option_name', ['CIBW_BUILD', 'CIBW_SKIP']) +@pytest.mark.parametrize('option_value, build_selector_patterns', [ + ('*-manylinux1_*', ['*-manylinux_*']), + ('*-macosx_10_6_intel', ['*-macosx_x86_64']), + ('*-macosx_10_9_x86_64', ['*-macosx_x86_64']), + ('cp37-macosx_10_9_x86_64', ['cp37-macosx_x86_64']), +]) +def test_build_selector_migrations(intercepted_build_args, monkeypatch, option_name, option_value, build_selector_patterns): + monkeypatch.setenv(option_name, option_value) + + main() + + intercepted_build_selector = intercepted_build_args.kwargs['build_selector'] + assert isinstance(intercepted_build_selector, BuildSelector) + + if option_name == 'CIBW_BUILD': + assert intercepted_build_selector.build_patterns == build_selector_patterns + else: + assert intercepted_build_selector.skip_patterns == build_selector_patterns + +