Use the ARCHS option to select universal2/arm64 builds
This commit is contained in:
@@ -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
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
|
||||
@@ -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
@@ -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:
|
||||
|
||||
Reference in New Issue
Block a user