2022-07-14 13:36:57 +02:00
|
|
|
from __future__ import annotations
|
|
|
|
|
|
2021-01-22 09:33:22 -05:00
|
|
|
import functools
|
|
|
|
|
import platform as platform_module
|
|
|
|
|
import re
|
2022-09-12 23:01:56 -04:00
|
|
|
import sys
|
2021-01-22 09:33:22 -05:00
|
|
|
from enum import Enum
|
|
|
|
|
|
2022-02-11 22:08:28 +01:00
|
|
|
from .typing import Final, Literal, PlatformName, assert_never
|
2021-01-22 09:33:22 -05:00
|
|
|
|
2022-02-11 22:08:28 +01:00
|
|
|
PRETTY_NAMES: Final = {"linux": "Linux", "macos": "macOS", "windows": "Windows"}
|
2021-01-22 09:33:22 -05:00
|
|
|
|
2022-09-24 23:04:46 +01:00
|
|
|
ARCH_SYNONYMS: Final[list[dict[PlatformName, str | None]]] = [
|
|
|
|
|
{"linux": "x86_64", "macos": "x86_64", "windows": "AMD64"},
|
|
|
|
|
{"linux": "i686", "macos": None, "windows": "x86"},
|
|
|
|
|
{"linux": "aarch64", "macos": "arm64", "windows": "ARM64"},
|
|
|
|
|
]
|
2022-09-12 23:01:56 -04:00
|
|
|
|
2021-01-22 09:33:22 -05:00
|
|
|
|
|
|
|
|
@functools.total_ordering
|
|
|
|
|
class Architecture(Enum):
|
|
|
|
|
value: str
|
|
|
|
|
|
|
|
|
|
# mac/linux archs
|
2021-05-03 11:45:43 -04:00
|
|
|
x86_64 = "x86_64"
|
2021-01-23 13:28:06 +00:00
|
|
|
|
|
|
|
|
# linux archs
|
2021-05-03 11:45:43 -04:00
|
|
|
i686 = "i686"
|
|
|
|
|
aarch64 = "aarch64"
|
|
|
|
|
ppc64le = "ppc64le"
|
|
|
|
|
s390x = "s390x"
|
2021-01-22 09:33:22 -05:00
|
|
|
|
2021-01-23 13:28:06 +00:00
|
|
|
# mac archs
|
2021-05-03 11:45:43 -04:00
|
|
|
universal2 = "universal2"
|
|
|
|
|
arm64 = "arm64"
|
2021-01-23 13:28:06 +00:00
|
|
|
|
2021-01-22 09:33:22 -05:00
|
|
|
# windows archs
|
2021-05-03 11:45:43 -04:00
|
|
|
x86 = "x86"
|
|
|
|
|
AMD64 = "AMD64"
|
2021-11-24 10:50:49 -08:00
|
|
|
ARM64 = "ARM64"
|
2021-01-22 09:33:22 -05:00
|
|
|
|
|
|
|
|
# Allow this to be sorted
|
2022-07-14 13:36:57 +02:00
|
|
|
def __lt__(self, other: Architecture) -> bool:
|
2021-01-22 09:33:22 -05:00
|
|
|
return self.value < other.value
|
|
|
|
|
|
2022-11-26 15:54:08 +00:00
|
|
|
def __str__(self) -> str:
|
|
|
|
|
return self.name
|
|
|
|
|
|
2021-01-22 09:33:22 -05:00
|
|
|
@staticmethod
|
2022-07-14 13:36:57 +02:00
|
|
|
def parse_config(config: str, platform: PlatformName) -> set[Architecture]:
|
2021-01-22 09:33:22 -05:00
|
|
|
result = set()
|
2021-05-03 11:45:43 -04:00
|
|
|
for arch_str in re.split(r"[\s,]+", config):
|
|
|
|
|
if arch_str == "auto":
|
2021-01-22 09:33:22 -05:00
|
|
|
result |= Architecture.auto_archs(platform=platform)
|
2021-05-03 11:45:43 -04:00
|
|
|
elif arch_str == "native":
|
2021-01-22 09:33:22 -05:00
|
|
|
result.add(Architecture(platform_module.machine()))
|
2021-05-03 11:45:43 -04:00
|
|
|
elif arch_str == "all":
|
2021-01-22 09:33:22 -05:00
|
|
|
result |= Architecture.all_archs(platform=platform)
|
2021-05-03 11:45:43 -04:00
|
|
|
elif arch_str == "auto64":
|
2021-01-31 20:41:18 -05:00
|
|
|
result |= Architecture.bitness_archs(platform=platform, bitness="64")
|
2021-05-03 11:45:43 -04:00
|
|
|
elif arch_str == "auto32":
|
2021-01-31 20:41:18 -05:00
|
|
|
result |= Architecture.bitness_archs(platform=platform, bitness="32")
|
2021-01-22 09:33:22 -05:00
|
|
|
else:
|
|
|
|
|
result.add(Architecture(arch_str))
|
|
|
|
|
return result
|
|
|
|
|
|
|
|
|
|
@staticmethod
|
2022-07-14 13:36:57 +02:00
|
|
|
def auto_archs(platform: PlatformName) -> set[Architecture]:
|
2022-09-12 23:01:56 -04:00
|
|
|
native_machine = platform_module.machine()
|
2021-01-23 13:28:06 +00:00
|
|
|
|
2022-09-12 23:01:56 -04:00
|
|
|
# Cross-platform support. Used for --print-build-identifiers or docker builds.
|
2022-09-24 23:04:46 +01:00
|
|
|
host_platform: PlatformName = (
|
2022-09-12 23:01:56 -04:00
|
|
|
"windows"
|
|
|
|
|
if sys.platform.startswith("win")
|
|
|
|
|
else ("macos" if sys.platform.startswith("darwin") else "linux")
|
|
|
|
|
)
|
|
|
|
|
|
2022-09-24 23:04:46 +01:00
|
|
|
native_architecture = Architecture(native_machine)
|
2022-09-12 23:01:56 -04:00
|
|
|
|
2022-09-24 23:04:46 +01:00
|
|
|
# we might need to rename the native arch to the machine we're running
|
|
|
|
|
# on, as the same arch can have different names on different platforms
|
|
|
|
|
if host_platform != platform:
|
|
|
|
|
for arch_synonym in ARCH_SYNONYMS:
|
|
|
|
|
if native_machine == arch_synonym.get(host_platform):
|
|
|
|
|
synonym = arch_synonym[platform]
|
|
|
|
|
|
|
|
|
|
if synonym is None:
|
|
|
|
|
# can't build anything on this platform
|
|
|
|
|
return set()
|
|
|
|
|
|
|
|
|
|
native_architecture = Architecture(synonym)
|
|
|
|
|
|
|
|
|
|
result = {native_architecture}
|
2022-09-12 23:01:56 -04:00
|
|
|
|
|
|
|
|
if platform == "linux" and Architecture.x86_64 in result:
|
2022-06-27 18:30:49 +01:00
|
|
|
# x86_64 machines can run i686 containers
|
2021-01-22 09:33:22 -05:00
|
|
|
result.add(Architecture.i686)
|
2021-01-23 13:28:06 +00:00
|
|
|
|
2022-09-12 23:01:56 -04:00
|
|
|
if platform == "windows" and Architecture.AMD64 in result:
|
2021-01-22 09:33:22 -05:00
|
|
|
result.add(Architecture.x86)
|
2021-01-23 13:28:06 +00:00
|
|
|
|
2021-01-22 09:33:22 -05:00
|
|
|
return result
|
|
|
|
|
|
|
|
|
|
@staticmethod
|
2022-07-14 13:36:57 +02:00
|
|
|
def all_archs(platform: PlatformName) -> set[Architecture]:
|
2022-02-27 14:16:37 -05:00
|
|
|
all_archs_map = {
|
2022-09-24 23:04:46 +01:00
|
|
|
"linux": {
|
|
|
|
|
Architecture.x86_64,
|
|
|
|
|
Architecture.i686,
|
|
|
|
|
Architecture.aarch64,
|
|
|
|
|
Architecture.ppc64le,
|
|
|
|
|
Architecture.s390x,
|
|
|
|
|
},
|
|
|
|
|
"macos": {Architecture.x86_64, Architecture.arm64, Architecture.universal2},
|
|
|
|
|
"windows": {Architecture.x86, Architecture.AMD64, Architecture.ARM64},
|
2022-02-27 14:16:37 -05:00
|
|
|
}
|
|
|
|
|
return all_archs_map[platform]
|
2021-01-22 09:33:22 -05:00
|
|
|
|
2021-01-31 20:41:18 -05:00
|
|
|
@staticmethod
|
2022-10-03 23:23:11 -04:00
|
|
|
# pylint: disable-next=inconsistent-return-statements
|
2022-07-14 13:36:57 +02:00
|
|
|
def bitness_archs(platform: PlatformName, bitness: Literal["64", "32"]) -> set[Architecture]:
|
2022-09-24 23:04:46 +01:00
|
|
|
archs_32 = {Architecture.i686, Architecture.x86}
|
2021-01-31 20:41:18 -05:00
|
|
|
auto_archs = Architecture.auto_archs(platform)
|
|
|
|
|
|
2021-05-03 11:45:43 -04:00
|
|
|
if bitness == "64":
|
2021-01-31 20:41:18 -05:00
|
|
|
return auto_archs - archs_32
|
2021-05-03 11:45:43 -04:00
|
|
|
elif bitness == "32":
|
2021-01-31 20:41:18 -05:00
|
|
|
return auto_archs & archs_32
|
|
|
|
|
else:
|
|
|
|
|
assert_never(bitness)
|
|
|
|
|
|
2021-01-22 09:33:22 -05:00
|
|
|
|
|
|
|
|
def allowed_architectures_check(
|
|
|
|
|
platform: PlatformName,
|
2022-07-14 13:36:57 +02:00
|
|
|
architectures: set[Architecture],
|
2021-01-22 09:33:22 -05:00
|
|
|
) -> None:
|
|
|
|
|
|
|
|
|
|
allowed_architectures = Architecture.all_archs(platform)
|
|
|
|
|
|
2021-05-03 11:45:43 -04:00
|
|
|
msg = f"{PRETTY_NAMES[platform]} only supports {sorted(allowed_architectures)} at the moment."
|
2021-01-22 09:33:22 -05:00
|
|
|
|
2021-05-03 11:45:43 -04:00
|
|
|
if platform != "linux":
|
|
|
|
|
msg += " If you want to set emulation architectures on Linux, use CIBW_ARCHS_LINUX instead."
|
2021-01-22 09:33:22 -05:00
|
|
|
|
|
|
|
|
if not architectures <= allowed_architectures:
|
2021-05-03 11:45:43 -04:00
|
|
|
msg = f"Invalid archs option {architectures}. " + msg
|
2021-01-22 09:33:22 -05:00
|
|
|
raise ValueError(msg)
|
|
|
|
|
|
|
|
|
|
if not architectures:
|
2021-05-03 11:45:43 -04:00
|
|
|
msg = "Empty archs option set. " + msg
|
2021-01-22 09:33:22 -05:00
|
|
|
raise ValueError(msg)
|