Implement CIBW_TEST_SKIP for individual archs of a universal2 wheel

This commit is contained in:
Joe Rickerby
2021-01-26 21:52:02 +00:00
parent d21b7cfc2e
commit b6f325c21a
3 changed files with 80 additions and 31 deletions
+36 -28
View File
@@ -8,6 +8,8 @@ import tempfile
from pathlib import Path
from typing import Any, Dict, List, NamedTuple, Optional, Sequence, Set, Tuple, cast
from typing_extensions import Literal
from .architecture import Architecture
from .environment import ParsedEnvironment
from .logger import log
@@ -342,37 +344,43 @@ def build(options: BuildOptions) -> None:
if options.test_command and options.test_selector(config.identifier):
machine_arch = platform.machine()
testing_archs: List[str] = []
testing_archs: List[Literal['x86_64', 'arm64']] = []
if machine_arch == 'x86_64':
if config.identifier.endswith('_arm64'):
log.warning(unwrap('''
While arm64 wheels can be built on x86_64, they cannot be tested. The
ability to test the arm64 wheels will be added in a future release of
cibuildwheel, once Apple Silicon CI runners are widely available.
'''))
testing_archs = []
elif config.identifier.endswith('_universal2'):
log.warning(unwrap('''
While universal2 wheels can be built on x86_64, the arm64 part of them
cannot currently be tested. The ability to test the arm64 part of a
universal2 wheel will be added in a future release of cibuildwheel, once
Apple Silicon CI runners are widely available.
'''))
testing_archs = ['x86_64']
else:
testing_archs = ['x86_64']
elif machine_arch == 'arm64':
if config.identifier.endswith('_x86_64'):
# testing using rosetta2 emulation
testing_archs = ['x86_64']
elif config.identifier.endswith('_universal2'):
# testing the x86_64 using rosetta2 emulation
testing_archs = ['arm64', 'x86_64']
else:
testing_archs = ['arm64']
if config.identifier.endswith('_arm64'):
testing_archs = ['arm64']
elif config.identifier.endswith('_universal2'):
testing_archs = ['x86_64', 'arm64']
else:
testing_archs = ['x86_64']
for testing_arch in testing_archs:
if config.identifier.endswith('_universal2'):
arch_specific_identifier = f'{config.identifier}:{testing_arch}'
if not options.test_selector(arch_specific_identifier):
continue
if machine_arch == 'x86_64' and testing_arch == 'arm64':
if config.identifier.endswith('_arm64'):
log.warning(unwrap('''
While arm64 wheels can be built on x86_64, they cannot be tested. The
ability to test the arm64 wheels will be added in a future release of
cibuildwheel, once Apple Silicon CI runners are widely available. To
silence this warning, set `CIBW_TEST_SKIP: *-macosx_arm64`.
'''))
elif config.identifier.endswith('_universal2'):
log.warning(unwrap('''
While universal2 wheels can be built on x86_64, the arm64 part of them
cannot currently be tested. The ability to test the arm64 part of a
universal2 wheel will be added in a future release of cibuildwheel, once
Apple Silicon CI runners are widely available. To silence this warning,
set `CIBW_TEST_SKIP: *-macosx_universal2:arm64`.
'''))
else:
raise RuntimeError('unreachable')
# skip this test
continue
log.step('Testing wheel...' if testing_arch == machine_arch else f'Testing wheel on {testing_arch}...')
# set up a virtual environment to install and test from, to make sure
+5
View File
@@ -544,11 +544,16 @@ CIBW_TEST_EXTRAS: test,qt
This will skip testing on any identifiers that match the given skip patterns (see [`CIBW_SKIP`](#build-skip)). This can be used to mask out tests for wheels that have missing dependencies upstream that are slow or hard to build, or to mask up slow tests on emulated architectures.
With macOS `universal2` wheels, you can also skip the the individual archs inside the wheel using an `:arch` suffix. For example, `cp39-macosx_universal2:x86_64` or `cp39-macosx_universal2:arm64`.
#### Examples
```yaml
# Will avoid testing on emulated architectures
CIBW_TEST_SKIP: "*-manylinux_{aarch64,ppc64le,s390x}"
# Skip trying to test arm64 builds on Intel Macs
CIBW_TEST_SKIP: "*-macosx_arm64 *-macosx_universal2:arm64"
```
+39 -3
View File
@@ -1,6 +1,6 @@
import platform
import subprocess
from typing import Tuple, cast
from typing import Tuple
import pytest
@@ -22,8 +22,8 @@ def get_xcode_version() -> Tuple[int, int]:
lines = output.splitlines()
_, version_str = lines[0].split()
version = tuple(int(x) for x in version_str.split('.'))
return cast(Tuple[int, int], version)
version_parts = version_str.split('.')
return (int(version_parts[0]), int(version_parts[1]))
def test_cross_compiled_build(tmp_path):
@@ -81,3 +81,39 @@ def test_cross_compiled_test(tmp_path, capfd, build_universal2):
expected_wheels = [w for w in ALL_MACOS_WHEELS if 'cp39' in w and 'universal2' not in w]
assert set(actual_wheels) == set(expected_wheels)
@pytest.mark.parametrize('skip_arm64_test', [False, True])
def test_universal2_testing(tmp_path, capfd, skip_arm64_test):
if utils.platform != 'macos':
pytest.skip('this test is only relevant to macos')
if get_xcode_version() < (12, 0):
pytest.skip('this test only works with Xcode 12 or greater')
if platform.machine() != 'x86_64':
pytest.skip('this test only works on x86_64')
project_dir = tmp_path / 'project'
basic_project.generate(project_dir)
actual_wheels = utils.cibuildwheel_run(project_dir, add_env={
'CIBW_BUILD': 'cp39-*',
'CIBW_TEST_COMMAND': '''python -c "import platform; print('running tests on ' + platform.machine())"''',
'CIBW_ARCHS': 'universal2',
'CIBW_TEST_SKIP': '*_universal2:arm64' if skip_arm64_test else '',
})
captured = capfd.readouterr()
if platform.machine() == 'x86_64':
assert 'running tests on x86_64' in captured.out
assert 'running tests on arm64' not in captured.out
warning_message = 'While universal2 wheels can be built on x86_64, the arm64 part of them cannot currently be tested'
if skip_arm64_test:
assert warning_message not in captured.err
else:
assert warning_message in captured.err
expected_wheels = [w for w in ALL_MACOS_WHEELS if 'cp39' in w and 'universal2' in w]
assert set(actual_wheels) == set(expected_wheels)