Use the ARCHS option to select universal2/arm64 builds

This commit is contained in:
Joe Rickerby
2021-01-05 15:14:32 +00:00
parent e405f3495e
commit df60457001
5 changed files with 83 additions and 22 deletions
+1 -1
View File
@@ -312,7 +312,7 @@ def print_build_identifiers(
elif platform == 'windows':
python_configurations = cibuildwheel.windows.get_python_configurations(build_selector)
elif platform == 'macos':
python_configurations = cibuildwheel.macos.get_python_configurations(build_selector)
python_configurations = cibuildwheel.macos.get_python_configurations(build_selector, architectures)
for config in python_configurations:
print(config.identifier)
+17 -14
View File
@@ -46,7 +46,8 @@ class PythonConfiguration(NamedTuple):
url: str
def get_python_configurations(build_selector: BuildSelector) -> List[PythonConfiguration]:
def get_python_configurations(build_selector: BuildSelector,
architectures: List[Architecture]) -> List[PythonConfiguration]:
python_configurations = [
# CPython
PythonConfiguration(version='2.7', identifier='cp27-macosx_x86_64', url='https://www.python.org/ftp/python/2.7.18/python-2.7.18-macosx10.9.pkg'),
@@ -58,19 +59,22 @@ def get_python_configurations(build_selector: BuildSelector) -> List[PythonConfi
PythonConfiguration(version='3.9', identifier='cp39-macosx_universal2', url='https://www.python.org/ftp/python/3.9.1/python-3.9.1-macos11.0.pkg'),
PythonConfiguration(version='3.9', identifier='cp39-macosx_arm64', url='https://www.python.org/ftp/python/3.9.1/python-3.9.1-macos11.0.pkg'),
# PyPy
# TODO: may not support 11.0 yet
PythonConfiguration(version='2.7', identifier='pp27-macosx_x86_64', url='https://downloads.python.org/pypy/pypy2.7-v7.3.3-osx64.tar.bz2'),
PythonConfiguration(version='3.6', identifier='pp36-macosx_x86_64', url='https://downloads.python.org/pypy/pypy3.6-v7.3.3-osx64.tar.bz2'),
PythonConfiguration(version='3.7', identifier='pp37-macosx_x86_64', url='https://downloads.python.org/pypy/pypy3.7-v7.3.3-osx64.tar.bz2'),
]
# skip builds as required
# filter out configs that don't match any of the selected architectures
python_configurations = [c for c in python_configurations
if any(c.identifier.endswith(a.value) for a in architectures)]
# skip builds as required by BUILD/SKIP
python_configurations = [c for c in python_configurations if build_selector(c.identifier)]
if get_macos_version() >= (11, 0):
# pypy doesn't work on macOS 11 yet
# See https://foss.heptapod.net/pypy/pypy/-/issues/3314
if any(c.identifier.startswith('pp') for c in python_configurations):
# pypy doesn't work on macOS 11 yet
# See https://foss.heptapod.net/pypy/pypy/-/issues/3314
log.warning(wrap_text('''
PyPy is currently unsupported when building on macOS 11. To build macOS PyPy wheels,
build on an older OS, such as macOS 10.15. To silence this warning, deselect PyPy by
@@ -81,14 +85,12 @@ def get_python_configurations(build_selector: BuildSelector) -> List[PythonConfi
if any(c.identifier.startswith('cp35') for c in python_configurations):
# CPython 3.5 doesn't work on macOS 11
log.warning(wrap_text('''
CPython is unsupported when building on macOS 11. To build CPython 3.5 wheels, build
on an older OS, such as macOS 10.15. To silence this warning, deselect CPython 3.5
by adding "cp35-macosx_x86_64" to your CIBW_SKIP option.
CPython 3.5 is unsupported when building on macOS 11. To build CPython 3.5 wheels,
build on an older OS, such as macOS 10.15. To silence this warning, deselect CPython
3.5 by adding "cp35-macosx_x86_64" to your CIBW_SKIP option.
'''))
python_configurations = [c for c in python_configurations if not c.identifier.startswith('cp35')]
python_configurations = [c for c in python_configurations if not c.identifier.startswith('cp35')]
return python_configurations
@@ -236,10 +238,11 @@ def setup_python(python_configuration: PythonConfiguration,
def build(options: BuildOptions) -> None:
if options.architectures != [Architecture.x86_64]:
allowed_archs = {Architecture.x86_64, Architecture.universal2, Architecture.arm64}
if set(options.architectures) <= allowed_archs:
raise ValueError(textwrap.dedent(f'''
Invalid archs option {options.architectures}. macOS only supports x86_64 for the moment.
If you want to set emulation architectures on Linux, use CIBW_ARCHS_LINUX instead.
Invalid archs option {options.architectures}. macOS only supports
these architectures: {', '.join(a.value for a in allowed_archs)}.
'''))
temp_dir = Path(tempfile.mkdtemp(prefix='cibuildwheel'))
@@ -253,7 +256,7 @@ def build(options: BuildOptions) -> None:
before_all_prepared = prepare_command(options.before_all, project='.', package=options.package_dir)
call([before_all_prepared], shell=True, env=env)
python_configurations = get_python_configurations(options.build_selector)
python_configurations = get_python_configurations(options.build_selector, options.architectures)
for config in python_configurations:
log.build_start(config.identifier)
+13
View File
@@ -127,11 +127,17 @@ class DependencyConstraints:
class Architecture(Enum):
# mac/linux archs
x86_64 = 'x86_64'
# linux archs
i686 = 'i686'
aarch64 = 'aarch64'
ppc64le = 'ppc64le'
s390x = 's390x'
# mac archs
universal2 = 'universal2'
arm64 = 'arm64'
# windows archs
x86 = 'x86'
AMD64 = 'AMD64'
@@ -150,11 +156,18 @@ class Architecture(Enum):
def auto_archs(platform: str) -> 'List[Architecture]':
native_architecture = Architecture(platform_module.machine())
result = [native_architecture]
if platform == 'linux' and native_architecture == Architecture.x86_64:
# x86_64 machines can run i686 docker containers
result.append(Architecture.i686)
if platform == 'windows' and native_architecture == Architecture.AMD64:
result.append(Architecture.x86)
if platform == 'macos' and native_architecture == Architecture.arm64:
# arm64 can build and test both archs of a universal2 wheel.
result.append(Architecture.universal2)
return result
+25
View File
@@ -0,0 +1,25 @@
import pytest
from . import test_projects, utils
basic_project = test_projects.new_c_project()
def test_cross_compiled_build(tmp_path):
if utils.platform != 'macos':
pytest.skip('this test is only relevant to macos')
project_dir = tmp_path / 'project'
basic_project.generate(project_dir)
actual_wheels = utils.cibuildwheel_run(project_dir, add_env={
'CIBW_ARCHS': 'x86_64, universal2, arm64',
})
expected_wheels = (
utils.expected_wheels('spam', '0.1.0', machine_arch='x86_64')
+ utils.expected_wheels('spam', '0.1.0', machine_arch='arm64')
)
assert set(actual_wheels) == set(expected_wheels)
# TODO: add a TEST_COMMAND test when using cross-compiling
+27 -7
View File
@@ -100,9 +100,11 @@ def expected_wheels(package_name, package_version, manylinux_versions=None,
if platform == 'linux':
python_abi_tags.append('cp27-cp27mu') # python 2.7 has 2 different ABI on manylinux
if platform == 'macos':
# TODO: perhaps drop Python 3.5 across the board?
if platform == 'macos' and get_macos_version() >= (11, 0):
# CPython 3.5 doesn't work on macOS 11.
python_abi_tags.remove('cp35-cp35m')
# pypy not supported on macOS 11.
python_abi_tags = [t for t in python_abi_tags if not t.startswith('pp')]
wheels = []
@@ -129,11 +131,17 @@ def expected_wheels(package_name, package_version, manylinux_versions=None,
elif platform == 'macos':
if python_abi_tag == 'cp39-cp39':
platform_tags = [
f'macosx_{macosx_deployment_target.replace(".", "_")}_x86_64',
f'macosx_{macosx_deployment_target.replace(".", "_")}_universal2.macosx_11_0_universal2',
'macosx_11_0_arm64',
]
if machine_arch == 'x86_64':
platform_tags = [
f'macosx_{macosx_deployment_target.replace(".", "_")}_x86_64',
]
elif machine_arch == 'arm64':
platform_tags = [
f'macosx_{macosx_deployment_target.replace(".", "_")}_universal2.macosx_11_0_universal2',
# macosx_deployment_target is ignored on arm64, because arm64 isn't supported on
# macOS earlier than 11.0
'macosx_11_0_arm64',
]
else:
platform_tags = [
f'macosx_{macosx_deployment_target.replace(".", "_")}_x86_64',
@@ -152,6 +160,18 @@ def expected_wheels(package_name, package_version, manylinux_versions=None,
return wheels
def get_macos_version():
'''
Returns the macOS major/minor version, as a tuple, e.g. (10, 15) or (11, 0)
These tuples can be used in comparisons, e.g.
(10, 14) <= (11, 0) == True
(11, 2) <= (11, 0) != True
'''
version_str, _, _ = pm.mac_ver()
return tuple(map(int, version_str.split(".")[:2]))
platform = None
if 'CIBW_PLATFORM' in os.environ: