Skip to content
Merged
Show file tree
Hide file tree
Changes from 21 commits
Commits
Show all changes
40 commits
Select commit Hold shift + click to select a range
acf4eb2
Add support for building iOS wheels.
freakboy3742 Feb 17, 2025
e992cef
Replace use of system() in test binary module.
freakboy3742 Feb 25, 2025
a450fba
Restored the 'minimal' approach of the minimal examples.
freakboy3742 Feb 25, 2025
ac8ab09
Split out platform details into standalone pages, and expand iOS plat…
freakboy3742 Feb 25, 2025
254b909
More doc corrections.
freakboy3742 Feb 25, 2025
a7a7b67
Merge branch 'main' into ios-support
freakboy3742 Feb 25, 2025
cead9fb
Bump support package to include fix for python/cpython#130292
freakboy3742 Feb 25, 2025
7b8b31e
Ensure iOS tests are all run on the same xdist worker.
freakboy3742 Feb 26, 2025
9c495a8
More iOS documentation tweaks.
freakboy3742 Feb 26, 2025
b622638
Merge branch 'main' into ios-support
freakboy3742 Mar 2, 2025
457d46a
Factor out common xcode version test utility.
freakboy3742 Mar 2, 2025
05ac4ae
Simplify iOS to a single platform with an expanded interpretation of …
freakboy3742 Mar 2, 2025
3b37676
I guess I should update the iOS tests as well...
freakboy3742 Mar 2, 2025
32b9203
Additional safety for missing iOS test output.
freakboy3742 Mar 2, 2025
c19bd4a
Remove DYLD_LIBRARY_PATH from the iOS environment.
freakboy3742 Mar 3, 2025
cc51dcc
Make test-sources mandatory for iOS builds.
freakboy3742 Mar 5, 2025
be267bd
Updates and clarifications to documentation.
freakboy3742 Mar 5, 2025
5420faf
Clarify what a slice is.
freakboy3742 Mar 6, 2025
fcf6f54
Normalize use of underscores in platform name.
freakboy3742 Mar 6, 2025
c4c88a7
Modify auto target to be matching CPU only.
freakboy3742 Mar 6, 2025
b542fb5
Use consistent ordering of platforms in examples.
freakboy3742 Mar 6, 2025
361b31a
Use consistent naming in iOS archiectures.
freakboy3742 Mar 6, 2025
a995526
Placate the linter.
freakboy3742 Mar 6, 2025
dca2338
Miscellaneous cleanups picked up by @joerick's review.
freakboy3742 Mar 6, 2025
8f2cb91
Correct the list of expected wheels.
freakboy3742 Mar 6, 2025
26f217c
Correct which 'native' we're actually checking.
freakboy3742 Mar 6, 2025
039c300
Correct the docs links so they're all relative.
freakboy3742 Mar 7, 2025
5208fc4
Correct the identification of free threaded builds.
freakboy3742 Mar 7, 2025
eedac55
Use target instead of host to describe the platform we're building for.
freakboy3742 Mar 8, 2025
b4e4a28
Rework iOS test to remove issue with log completeness.
freakboy3742 Mar 8, 2025
e477026
Convert errors to FatalError
freakboy3742 Mar 8, 2025
2ebefab
Removed a repeated check for a valid python.
freakboy3742 Mar 8, 2025
2b08934
Update bin/update_pythons.py to update iOS support packages.
freakboy3742 Mar 9, 2025
3580d6e
Document that iOS CI is available on other platforms.
freakboy3742 Mar 10, 2025
b39c6eb
Restore a comment needed for some platforms.
freakboy3742 Mar 10, 2025
6b9b033
Small cleanups identified in code review
freakboy3742 Mar 10, 2025
f29439b
Simplify logic to appease linter.
freakboy3742 Mar 11, 2025
1ea0fab
Merge branch 'main' into ios-support
freakboy3742 Mar 11, 2025
4a5fef5
Modify dependency constraint handling to use new API.
freakboy3742 Mar 11, 2025
6a8f410
Cosmetic change to trigger a CI rebuild.
freakboy3742 Mar 11, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 5 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -58,12 +58,12 @@ Usage
| | Linux | macOS | Windows | Linux ARM | macOS ARM | Windows ARM | iOS |
|-----------------|-------|-------|---------|-----------|-----------|-------------|-----|
| GitHub Actions | ✅ | ✅ | ✅ | ✅ | ✅ | ✅² | ✅³ |
| Azure Pipelines | ✅ | ✅ | ✅ | | ✅ | ✅² | |
| Azure Pipelines | ✅ | ✅ | ✅ | | ✅ | ✅² | ✅³ |
| Travis CI | ✅ | | ✅ | ✅ | | | |
| AppVeyor | ✅ | ✅ | ✅ | | ✅ | ✅² | |
| CircleCI | ✅ | ✅ | | ✅ | ✅ | | |
| Gitlab CI | ✅ | ✅ | ✅ | ✅¹ | ✅ | | |
| Cirrus CI | ✅ | ✅ | ✅ | ✅ | ✅ | | |
| AppVeyor | ✅ | ✅ | ✅ | | ✅ | ✅² | ✅³ |
| CircleCI | ✅ | ✅ | | ✅ | ✅ | | ✅³ |
| Gitlab CI | ✅ | ✅ | ✅ | ✅¹ | ✅ | | ✅³ |
| Cirrus CI | ✅ | ✅ | ✅ | ✅ | ✅ | | ✅³ |

<sup>¹ [Requires emulation](https://cibuildwheel.pypa.io/en/stable/faq/#emulation), distributed separately. Other services may also support Linux ARM through emulation or third-party build hosts, but these are not tested in our CI.</sup><br>
<sup>² [Uses cross-compilation](https://cibuildwheel.pypa.io/en/stable/faq/#windows-arm64). It is not possible to test `arm64` on this CI platform.</sup><br>
Expand Down
61 changes: 55 additions & 6 deletions bin/update_pythons.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,13 +44,13 @@ class ConfigWinPP(TypedDict):
url: str


class ConfigMacOS(TypedDict):
class ConfigApple(TypedDict):
identifier: str
version: str
url: str


AnyConfig = ConfigWinCP | ConfigWinPP | ConfigMacOS
AnyConfig = ConfigWinCP | ConfigWinPP | ConfigApple


# The following set of "Versions" classes allow the initial call to the APIs to
Expand Down Expand Up @@ -154,7 +154,7 @@ def update_version_windows(self, spec: Specifier) -> ConfigWinCP:
url=url,
)

def update_version_macos(self, spec: Specifier) -> ConfigMacOS:
def update_version_macos(self, spec: Specifier) -> ConfigApple:
if self.arch not in {"64", "ARM64"}:
msg = f"'{self.arch}' arch not supported yet on macOS"
raise RuntimeError(msg)
Expand All @@ -178,7 +178,7 @@ def update_version_macos(self, spec: Specifier) -> ConfigMacOS:
if "" in rf["platform"] == "darwin" and rf["arch"] == arch
)

return ConfigMacOS(
return ConfigApple(
identifier=identifier,
version=f"{version.major}.{version.minor}",
url=url,
Expand All @@ -204,7 +204,7 @@ def __init__(self) -> None:

def update_version_macos(
self, identifier: str, version: Version, spec: Specifier
) -> ConfigMacOS | None:
) -> ConfigApple | None:
# see note above on Specifier.filter
unsorted_versions = spec.filter(self.versions_dict)
sorted_versions = sorted(unsorted_versions, reverse=True)
Expand All @@ -223,7 +223,7 @@ def update_version_macos(

urls = [rf["url"] for rf in file_info if file_ident in rf["url"]]
if urls:
return ConfigMacOS(
return ConfigApple(
identifier=identifier,
version=f"{new_version.major}.{new_version.minor}",
url=urls[0],
Expand All @@ -232,6 +232,48 @@ def update_version_macos(
return None


class CPythonIOSVersions:
def __init__(self) -> None:
response = requests.get(
"https://api.github.com/repos/beeware/Python-Apple-support/releases",
headers={
"Accept": "application/vnd.github+json",
"X-Github-Api-Version": "2022-11-28",
},
)
response.raise_for_status()

releases_info = response.json()
self.versions_dict: dict[Version, dict[int, str]] = {}

# Each release has a name like "3.13-b4"
for release in releases_info:
py_version, build = release["name"].split("-")
version = Version(py_version)
self.versions_dict.setdefault(version, {})

# There are several release assets associated with each release;
# The name of the asset will be something like
# "Python-3.11-iOS-support.b4.tar.gz". Store all builds that are
# "-iOS-support" builds, retaining the download URL.
for asset in release["assets"]:
filename, build, _, _ = asset["name"].rsplit(".", 3)
if filename.endswith("-iOS-support"):
self.versions_dict[version][int(build[1:])] = asset["browser_download_url"]

def update_version_ios(self, identifier: str, version: Version) -> ConfigApple | None:
# Return a config using the highest build number for the given version.
urls = [url for _, url in sorted(self.versions_dict.get(version, {}).items())]
if urls:
return ConfigApple(
identifier=identifier,
version=str(version),
url=urls[-1],
)

return None


# This is a universal interface to all the above Versions classes. Given an
# identifier, it updates a config dict.

Expand All @@ -250,6 +292,8 @@ def __init__(self) -> None:
self.macos_pypy = PyPyVersions("64")
self.macos_pypy_arm64 = PyPyVersions("ARM64")

self.ios_cpython = CPythonIOSVersions()

def update_config(self, config: MutableMapping[str, str]) -> None:
identifier = config["identifier"]
version = Version(config["version"])
Expand Down Expand Up @@ -282,6 +326,8 @@ def update_config(self, config: MutableMapping[str, str]) -> None:
config_update = self.windows_t_arm64.update_version_windows(spec)
elif "win_arm64" in identifier and identifier.startswith("cp"):
config_update = self.windows_arm64.update_version_windows(spec)
elif "ios" in identifier:
config_update = self.ios_cpython.update_version_ios(identifier, version)

assert config_update is not None, f"{identifier} not found!"
config.update(**config_update)
Expand Down Expand Up @@ -317,6 +363,9 @@ def update_pythons(force: bool, level: str) -> None:
for config in configs["macos"]["python_configurations"]:
all_versions.update_config(config)

for config in configs["ios"]["python_configurations"]:
all_versions.update_config(config)

result_toml = dump_python_configurations(configs)

rich.print() # spacer
Expand Down
33 changes: 19 additions & 14 deletions cibuildwheel/architecture.py
Original file line number Diff line number Diff line change
Expand Up @@ -66,9 +66,9 @@ class Architecture(StrEnum):

# iOS "multiarch" architectures that include both
# the CPU architecture and the ABI.
arm64_device = "arm64-iphoneos"
arm64_simulator = "arm64-iphonesimulator"
x86_64_simulator = "x86_64-iphonesimulator"
arm64_iphoneos = auto()
arm64_iphonesimulator = auto()
x86_64_iphonesimulator = auto()

@staticmethod
def parse_config(config: str, platform: PlatformName) -> "set[Architecture]":
Expand Down Expand Up @@ -113,9 +113,9 @@ def native_arch(platform: PlatformName) -> "Architecture | None":
# simulator for the macOS native platform.
if host_platform == "macos":
if native_architecture == Architecture.x86_64:
return Architecture.x86_64_simulator
return Architecture.x86_64_iphonesimulator
else:
return Architecture.arm64_simulator
return Architecture.arm64_iphonesimulator
else:
return None

Expand Down Expand Up @@ -152,12 +152,17 @@ def auto_archs(platform: PlatformName) -> "set[Architecture]":
result.add(Architecture.x86)

elif platform == "ios":
# iOS defaults to building all architectures
result = {
Architecture.x86_64_simulator,
Architecture.arm64_simulator,
Architecture.arm64_device,
}
# iOS defaults to building all targets with the same CPU architecture
# as the native simulator architecture
if native_arch == Architecture.x86_64_iphonesimulator:
result = {
Architecture.x86_64_iphonesimulator,
}
else:
result = {
Architecture.arm64_iphonesimulator,
Architecture.arm64_iphoneos,
}

return result

Expand All @@ -176,9 +181,9 @@ def all_archs(platform: PlatformName) -> "set[Architecture]":
"windows": {Architecture.x86, Architecture.AMD64, Architecture.ARM64},
"pyodide": {Architecture.wasm32},
"ios": {
Architecture.x86_64_simulator,
Architecture.arm64_simulator,
Architecture.arm64_device,
Architecture.x86_64_iphonesimulator,
Architecture.arm64_iphonesimulator,
Architecture.arm64_iphoneos,
},
}
return all_archs_map[platform]
Expand Down
Loading
Loading