Skip to content

Commit ed3fc9c

Browse files
committed
- chardet module v7 broke MacOS universal build, pin the module to <7
- Add universal2 check early on to make sure every module supports x86 and arm64
1 parent aea9eb8 commit ed3fc9c

2 files changed

Lines changed: 80 additions & 1 deletion

File tree

.github/workflows/mac.yml

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,85 @@ jobs:
104104
- name: List modules and their versions
105105
run: python3.13 -m pip freeze
106106

107+
- name: Verify universal2 extension modules
108+
shell: bash
109+
run: |
110+
python3.13 - <<'PY'
111+
import importlib.machinery
112+
import pathlib
113+
import fnmatch
114+
import site
115+
import subprocess
116+
import sys
117+
118+
ext_suffixes = tuple(importlib.machinery.EXTENSION_SUFFIXES)
119+
if not ext_suffixes:
120+
print("Could not determine extension suffixes.", file=sys.stderr)
121+
sys.exit(1)
122+
123+
allowlist_patterns = [
124+
# Add glob patterns for extension-module paths to exempt from universal2 checks.
125+
# Example: "*/site-packages/somepkg/someext*.so"
126+
]
127+
128+
def iter_site_package_roots() -> list[pathlib.Path]:
129+
roots = set()
130+
for path in site.getsitepackages():
131+
roots.add(pathlib.Path(path).resolve())
132+
user_site = site.getusersitepackages()
133+
if user_site:
134+
roots.add(pathlib.Path(user_site).resolve())
135+
return sorted(roots)
136+
137+
def is_extension_module(path: pathlib.Path) -> bool:
138+
return any(path.name.endswith(suffix) for suffix in ext_suffixes)
139+
140+
def is_allowlisted(path: pathlib.Path) -> bool:
141+
normalized = path.as_posix()
142+
return any(fnmatch.fnmatch(normalized, pattern) for pattern in allowlist_patterns)
143+
144+
def check_arches(path: pathlib.Path) -> tuple[bool, str]:
145+
result = subprocess.run(
146+
["lipo", "-archs", str(path)],
147+
check=False,
148+
capture_output=True,
149+
text=True,
150+
)
151+
if result.returncode != 0:
152+
return False, f"lipo failed: {result.stderr.strip()}"
153+
archs = set(result.stdout.strip().split())
154+
ok = {"arm64", "x86_64"}.issubset(archs)
155+
return ok, " ".join(sorted(archs))
156+
157+
failures = []
158+
checked = 0
159+
160+
for root in iter_site_package_roots():
161+
if not root.exists():
162+
continue
163+
for path in root.rglob("*"):
164+
if not path.is_file() or not is_extension_module(path):
165+
continue
166+
if is_allowlisted(path):
167+
continue
168+
checked += 1
169+
ok, details = check_arches(path)
170+
if not ok:
171+
failures.append((path, details))
172+
173+
print(f"Checked {checked} compiled extension modules for universal2 slices.")
174+
175+
if failures:
176+
print("Universal2 guard failed. Non-universal extension modules found:", file=sys.stderr)
177+
for path, details in failures[:50]:
178+
print(f" - {path}: {details}", file=sys.stderr)
179+
if len(failures) > 50:
180+
print(f" ... and {len(failures) - 50} more", file=sys.stderr)
181+
sys.exit(1)
182+
183+
print("Universal2 guard passed: all extension modules include arm64 and x86_64.")
184+
PY
185+
107186
- name: Build application
108187
id: build_app
109188
run: ./build.sh

requirements.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ lz4>=4.3.2
1515
psutil>=5.9.5
1616
json5>=0.9.14
1717
bs4>=0.0.1
18-
chardet>=5.2.0
18+
chardet>=5.2.0,<7
1919
cryptography>=42.0.5
2020
rsa>=4.9
2121
polib>=1.1.1

0 commit comments

Comments
 (0)