diff --git a/cibuildwheel/__main__.py b/cibuildwheel/__main__.py index 010d9eea..8f65f28b 100644 --- a/cibuildwheel/__main__.py +++ b/cibuildwheel/__main__.py @@ -11,16 +11,15 @@ import cibuildwheel import cibuildwheel.linux import cibuildwheel.macos import cibuildwheel.windows +from cibuildwheel.architecture import Architecture, allowed_architectures_check from cibuildwheel.environment import EnvironmentParseError, parse_environment from cibuildwheel.typing import PLATFORMS, PlatformName, assert_never from cibuildwheel.util import ( - Architecture, BuildOptions, BuildSelector, DependencyConstraints, TestSelector, Unbuffered, - allowed_architectures_check, detect_ci_provider, resources_dir, ) @@ -259,7 +258,7 @@ def main() -> None: print_preamble(platform, build_options) try: - allowed_architectures_check(platform, build_options) + allowed_architectures_check(platform, build_options.architectures) except ValueError as err: print("cibuildwheel:", *err.args, file=sys.stderr) sys.exit(4) diff --git a/cibuildwheel/architecture.py b/cibuildwheel/architecture.py new file mode 100644 index 00000000..f7bf4354 --- /dev/null +++ b/cibuildwheel/architecture.py @@ -0,0 +1,86 @@ +import functools +import platform as platform_module +import re +from enum import Enum +from typing import Set + +from .typing import PlatformName, assert_never + +PRETTY_NAMES = {'linux': 'Linux', 'macos': 'macOS', 'windows': 'Windows'} + + +@functools.total_ordering +class Architecture(Enum): + value: str + + # mac/linux archs + x86_64 = 'x86_64' + i686 = 'i686' + aarch64 = 'aarch64' + ppc64le = 'ppc64le' + s390x = 's390x' + + # windows archs + x86 = 'x86' + AMD64 = 'AMD64' + + # Allow this to be sorted + def __lt__(self, other: "Architecture") -> bool: + return self.value < other.value + + @staticmethod + def parse_config(config: str, platform: PlatformName) -> 'Set[Architecture]': + result = set() + for arch_str in re.split(r'[\s,]+', config): + if arch_str == 'auto': + result |= Architecture.auto_archs(platform=platform) + elif arch_str == 'native': + result.add(Architecture(platform_module.machine())) + elif arch_str == 'all': + result |= Architecture.all_archs(platform=platform) + else: + result.add(Architecture(arch_str)) + return result + + @staticmethod + def auto_archs(platform: PlatformName) -> 'Set[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.add(Architecture.i686) + if platform == 'windows' and native_architecture == Architecture.AMD64: + result.add(Architecture.x86) + return result + + @staticmethod + def all_archs(platform: PlatformName) -> 'Set[Architecture]': + if platform == 'linux': + return {Architecture.x86_64, Architecture.i686, Architecture.aarch64, Architecture.ppc64le, Architecture.s390x} + elif platform == 'macos': + return {Architecture.x86_64} + elif platform == 'windows': + return {Architecture.x86, Architecture.AMD64} + else: + assert_never(platform) + + +def allowed_architectures_check( + platform: PlatformName, + architectures: Set[Architecture], +) -> None: + + allowed_architectures = Architecture.all_archs(platform) + + msg = f'{PRETTY_NAMES[platform]} only supports {sorted(allowed_architectures)} at the moment.' + + if platform != 'linux': + msg += ' If you want to set emulation architectures on Linux, use CIBW_ARCHS_LINUX instead.' + + if not architectures <= allowed_architectures: + msg = f'Invalid archs option {architectures}. ' + msg + raise ValueError(msg) + + if not architectures: + msg = 'Empty archs option set. ' + msg + raise ValueError(msg) diff --git a/cibuildwheel/linux.py b/cibuildwheel/linux.py index ce725b55..13354f43 100644 --- a/cibuildwheel/linux.py +++ b/cibuildwheel/linux.py @@ -4,11 +4,11 @@ import textwrap from pathlib import Path, PurePath from typing import List, NamedTuple, Set +from .architecture import Architecture from .docker_container import DockerContainer from .logger import log from .typing import PathOrStr from .util import ( - Architecture, BuildOptions, BuildSelector, NonPlatformWheelError, diff --git a/cibuildwheel/util.py b/cibuildwheel/util.py index 33435c16..1baf71a9 100644 --- a/cibuildwheel/util.py +++ b/cibuildwheel/util.py @@ -1,9 +1,6 @@ import fnmatch -import functools import itertools import os -import platform as platform_module -import re import ssl import sys import textwrap @@ -17,8 +14,9 @@ import bracex import certifi import toml +from .architecture import Architecture from .environment import ParsedEnvironment -from .typing import PathOrStr, PlatformName, assert_never +from .typing import PathOrStr, PlatformName if sys.version_info < (3, 9): from importlib_resources import files @@ -163,62 +161,6 @@ class DependencyConstraints: return f'{self.__class__.__name__}{self.base_file_path!r})' -@functools.total_ordering -class Architecture(Enum): - value: str - - # mac/linux archs - x86_64 = 'x86_64' - i686 = 'i686' - aarch64 = 'aarch64' - ppc64le = 'ppc64le' - s390x = 's390x' - - # windows archs - x86 = 'x86' - AMD64 = 'AMD64' - - # Allow this to be sorted - def __lt__(self, other: "Architecture") -> bool: - return self.value < other.value - - @staticmethod - def parse_config(config: str, platform: PlatformName) -> 'Set[Architecture]': - result = set() - for arch_str in re.split(r'[\s,]+', config): - if arch_str == 'auto': - result |= Architecture.auto_archs(platform=platform) - elif arch_str == 'native': - result.add(Architecture(platform_module.machine())) - elif arch_str == 'all': - result |= Architecture.all_archs(platform=platform) - else: - result.add(Architecture(arch_str)) - return result - - @staticmethod - def auto_archs(platform: PlatformName) -> 'Set[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.add(Architecture.i686) - if platform == 'windows' and native_architecture == Architecture.AMD64: - result.add(Architecture.x86) - return result - - @staticmethod - def all_archs(platform: PlatformName) -> 'Set[Architecture]': - if platform == 'linux': - return {Architecture.x86_64, Architecture.i686, Architecture.aarch64, Architecture.ppc64le, Architecture.s390x} - elif platform == 'macos': - return {Architecture.x86_64} - elif platform == 'windows': - return {Architecture.x86, Architecture.AMD64} - else: - assert_never(platform) - - class BuildOptions(NamedTuple): package_dir: Path output_dir: Path @@ -286,27 +228,3 @@ def detect_ci_provider() -> Optional[CIProvider]: return CIProvider.other else: return None - - -PRETTY_NAMES = {'linux': 'Linux', 'macos': 'macOS', 'windows': 'Windows'} - - -def allowed_architectures_check( - platform: PlatformName, - options: BuildOptions, -) -> None: - - allowed_architectures = Architecture.all_archs(platform) - - msg = f'{PRETTY_NAMES[platform]} only supports {sorted(allowed_architectures)} at the moment.' - - if platform != 'linux': - msg += ' If you want to set emulation architectures on Linux, use CIBW_ARCHS_LINUX instead.' - - if not options.architectures <= allowed_architectures: - msg = f'Invalid archs option {options.architectures}. ' + msg - raise ValueError(msg) - - if not options.architectures: - msg = 'Empty archs option set. ' + msg - raise ValueError(msg) diff --git a/cibuildwheel/windows.py b/cibuildwheel/windows.py index e2a6d254..4d3487ca 100644 --- a/cibuildwheel/windows.py +++ b/cibuildwheel/windows.py @@ -9,11 +9,11 @@ from zipfile import ZipFile import toml +from .architecture import Architecture from .environment import ParsedEnvironment from .logger import log from .typing import PathOrStr from .util import ( - Architecture, BuildOptions, BuildSelector, NonPlatformWheelError, diff --git a/unit_test/main_tests/main_platform_test.py b/unit_test/main_tests/main_platform_test.py index e0897dc8..a06ffe68 100644 --- a/unit_test/main_tests/main_platform_test.py +++ b/unit_test/main_tests/main_platform_test.py @@ -89,9 +89,9 @@ def test_archs_argument(platform, intercepted_build_args, monkeypatch, use_env_v monkeypatch.setattr(sys, 'argv', sys.argv + ['--archs', 'ppc64le']) if platform in {'macos', 'windows'}: - with pytest.raises(SystemExit) as err: + with pytest.raises(SystemExit) as exit: main() - assert err.value.args == (4,) + assert exit.value.args == (4,) else: main()