diff --git a/AGENTS.md b/AGENTS.md index 0f10fc0..76cadf0 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -19,7 +19,7 @@ for validation are not the scope of a general fix. Credit reference repositories when their work informed a change. Build: python3 tools/build.py -Test: python3 tools/test.py dist/WhateverXe-Graphics-0.2.0.pkg +Test: python3 tools/test.py dist/WhateverXe-Graphics-0.3.1.pkg Preserve signed payloads exactly unless deliberately updating and requalifying an asset. Never sign original Apple compiler backends again. Keep signed bundles diff --git a/CHANGELOG.md b/CHANGELOG.md index 89b4d60..df057f8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,19 @@ # Changelog +## 0.3.1 + +### Packaging correction + +- Correct the AppleIntelTGLCompat dependency metadata that prevented installation of 0.3.0. + +### Changes carried over from 0.3.0 + +- Add graphics payloads for Alder Lake-H/P/U and Raptor Lake-H/P/U, with the updated Compat provider for fixed HDMI/DisplayPort support. Use the latest [WhateverXe](https://github.com/b00t0x/WhateverXe/releases). +- Fix shader compilation failures on Sonoma–Tahoe using the OS-native AIR converter, based on work in [JulioNectar/Hackintosh-XPS13Plus-IrisXe-Tahoe](https://github.com/JulioNectar/Hackintosh-XPS13Plus-IrisXe-Tahoe/tree/0ad1bc5d3b9e73c918be174f791f4d739cde51e9/macos/src). +- Accept compatible compiler updates on Sonoma–Tahoe without requiring an exact UUID match; retain API and image checks and remove the previous converter fallback. + +See [WEX compatibility and known issues](https://github.com/b00t0x/WhateverXe#compatibility) for remaining limitations. + ## 0.3.0 Use the latest [WhateverXe](https://github.com/b00t0x/WhateverXe/releases) release for the new mobile GPU and fixed TC display support. diff --git a/README.md b/README.md index e8a1f03..59b2b11 100644 --- a/README.md +++ b/README.md @@ -90,7 +90,7 @@ On macOS with Xcode Command Line Tools and Python 3.10 or newer: ```sh python3 tools/build.py -python3 tools/test.py dist/WhateverXe-Graphics-0.3.0.pkg +python3 tools/test.py dist/WhateverXe-Graphics-0.3.1.pkg ``` The test also needs Node.js and `rcodesign` 0.29.0; CI supplies both. The builder diff --git a/README_ja.md b/README_ja.md index 0d9deb0..3473bdd 100644 --- a/README_ja.md +++ b/README_ja.md @@ -85,7 +85,7 @@ Xcode Command Line ToolsとPython 3.10以上を用意したmacOSで実行しま ```sh python3 tools/build.py -python3 tools/test.py dist/WhateverXe-Graphics-0.3.0.pkg +python3 tools/test.py dist/WhateverXe-Graphics-0.3.1.pkg ``` 検証にはNode.jsと`rcodesign` 0.29.0も必要です。CIでは両方を用意します。 diff --git a/docs/SOURCES.md b/docs/SOURCES.md index bc5fe2e..46d577d 100644 --- a/docs/SOURCES.md +++ b/docs/SOURCES.md @@ -10,7 +10,7 @@ for this repository. Source and its shared headers remain in [WhateverXe](https://github.com/b00t0x/WhateverXe). All supported macOS versions use one RELEASE build of AppleIntelTGLCompat 0.6.0 from WEX commit -[`919e9af`](https://github.com/b00t0x/WhateverXe/tree/919e9af08258cfe8ffde1e47b952155381ec30db/AppleIntelTGLCompat). +[`5ea5f00`](https://github.com/b00t0x/WhateverXe/tree/5ea5f002db9dc53ea72d6ec1f3722d4ed4adbe39/AppleIntelTGLCompat). Build that checkout with `python3 tools/build.py --release`, then sign the resulting kext with the Mod chain before importing the complete bundle into `payloads/Common/Library/Extensions/`. The package contains no per-OS provider @@ -24,6 +24,8 @@ revision, build configuration, source file hash and final signed executable hash The build strips debug maps before signing. These source references do not promise byte-identical rebuilding with a different compiler or signing invocation. The provider source and its shared headers belong to the same WEX revision. +Its compatibility floor is 0.5.0, matching the bundled framebuffer dependency. +The provider release version is independent of this ABI compatibility floor. ## Graphics and compiler payloads diff --git a/docs/payload-provenance.json b/docs/payload-provenance.json index 093910f..b1aa169 100644 --- a/docs/payload-provenance.json +++ b/docs/payload-provenance.json @@ -2,15 +2,16 @@ "provider_source_repository": "https://github.com/b00t0x/WhateverXe", "providers": { "Common": { - "source_commit": "919e9af08258cfe8ffde1e47b952155381ec30db", + "source_commit": "5ea5f002db9dc53ea72d6ec1f3722d4ed4adbe39", "source_file": "AppleIntelTGLCompat/AppleIntelTGLCompat.cpp", "source_file_sha256": "42288d2c53f1a8df67307ef35f67477906d79c197d0b3c65a6700c86dec660dc", "version": "0.6.0", "configuration": "RELEASE", "build_command": "python3 tools/build.py --release", - "sha256": "d713c30fd1144cb4acfbca2c72118d22eb6f6ae99d2055e3dbc626d9898509e3", + "sha256": "62aa75c694ca633cfe0b24e7a75c713bccd2aabb568d125a7e24205361998830", "policy_source_file": "AppleIntelTGLCompat/GraphicsPolicy.plist", - "policy_source_sha256": "dd9555491052208445abbd9daa96dd0a9dd4e5e71b1e6a14355224199cfb17eb" + "policy_source_sha256": "dd9555491052208445abbd9daa96dd0a9dd4e5e71b1e6a14355224199cfb17eb", + "compatible_version": "0.5.0" } }, "amfipass_sha256": "71f41de42e355d2a83e6f093ef34a5b24d0a9c9a9085830b2317f1b874f56250", diff --git a/payloads/Common/Library/Extensions/AppleIntelTGLCompat.kext/Contents/Info.plist b/payloads/Common/Library/Extensions/AppleIntelTGLCompat.kext/Contents/Info.plist index c8895ee..2f54745 100644 --- a/payloads/Common/Library/Extensions/AppleIntelTGLCompat.kext/Contents/Info.plist +++ b/payloads/Common/Library/Extensions/AppleIntelTGLCompat.kext/Contents/Info.plist @@ -50,7 +50,7 @@ OSBundleCompatibleVersion - 0.6.0 + 0.5.0 OSBundleLibraries com.apple.iokit.IOPCIFamily diff --git a/payloads/Common/Library/Extensions/AppleIntelTGLCompat.kext/Contents/MacOS/AppleIntelTGLCompat b/payloads/Common/Library/Extensions/AppleIntelTGLCompat.kext/Contents/MacOS/AppleIntelTGLCompat index c18333f..2e21f46 100755 Binary files a/payloads/Common/Library/Extensions/AppleIntelTGLCompat.kext/Contents/MacOS/AppleIntelTGLCompat and b/payloads/Common/Library/Extensions/AppleIntelTGLCompat.kext/Contents/MacOS/AppleIntelTGLCompat differ diff --git a/tools/kext_dependencies.py b/tools/kext_dependencies.py new file mode 100644 index 0000000..08dae0d --- /dev/null +++ b/tools/kext_dependencies.py @@ -0,0 +1,35 @@ +"""Check dependencies resolved within one selected graphics payload set.""" +import plistlib +import re + + +def version(value): + # These payloads use numeric release versions; reject unsupported spellings. + if not isinstance(value, str) or not re.fullmatch(r'\d+\.\d+\.\d+', value): + raise ValueError(f'unsupported payload dependency version: {value!r}') + return tuple(map(int, value.split('.'))) + + +def check_dependencies(plists, label): + providers = {} + for path in plists: + info = plistlib.loads(path.read_bytes()) + identifier = info['CFBundleIdentifier'] + if identifier in providers: + raise ValueError(f'{label}: duplicate provider {identifier}') + providers[identifier] = info + checked = 0 + for client, info in providers.items(): + for dependency, requested in info.get('OSBundleLibraries', {}).items(): + provider = providers.get(dependency) + if provider is None: + if dependency.startswith('org.b00t0x.'): + raise ValueError(f'{label}: {client} requires missing provider {dependency}') + continue # System kexts are supplied by the target OS. + current = provider['CFBundleVersion'] + compatible = provider['OSBundleCompatibleVersion'] + if not version(compatible) <= version(requested) <= version(current): + raise ValueError(f'{label}: {client} requires {dependency} {requested}, ' + f'outside provider compatibility range {compatible}–{current}') + checked += 1 + return checked diff --git a/tools/policy.json b/tools/policy.json index 1cf230d..7fd56a6 100644 --- a/tools/policy.json +++ b/tools/policy.json @@ -1,5 +1,5 @@ { - "package_version": "0.3.0", + "package_version": "0.3.1", "systems": [ { "name": "Big Sur", diff --git a/tools/test.py b/tools/test.py index 3970f7d..cbe6752 100644 --- a/tools/test.py +++ b/tools/test.py @@ -8,12 +8,14 @@ import tempfile import xml.etree.ElementTree as ET from pathlib import Path +from kext_dependencies import check_dependencies parser = argparse.ArgumentParser(description=__doc__) parser.add_argument('package', type=Path) parser.add_argument('--rcodesign', default='rcodesign') args = parser.parse_args() subprocess.run([sys.executable, str(Path(__file__).with_name('test_uninstall.py'))], check=True) +subprocess.run([sys.executable, str(Path(__file__).with_name('test_dependencies.py'))], check=True) subprocess.run([sys.executable, str(Path(__file__).with_name('verify.py')), '--rcodesign', args.rcodesign], check=True) manifest = json.loads((args.package.parent / 'manifest.json').read_text()) assert (args.package.parent / 'SHA256SUMS').read_text() == ( @@ -76,6 +78,8 @@ assert not (payloads['Common'].keys() & payloads[build].keys()) actual = payloads['Common'] | payloads[build] assert actual.keys() == expected.keys() + plists = [p for rel, p in actual.items() if rel.startswith('Library/Extensions/') and rel.endswith('.kext/Contents/Info.plist')] + assert check_dependencies(plists, build) > 0 for rel, p in actual.items(): data = p.read_bytes() assert hashlib.sha256(data).hexdigest() == expected[rel]['sha256'], rel diff --git a/tools/test_dependencies.py b/tools/test_dependencies.py new file mode 100644 index 0000000..f0133b2 --- /dev/null +++ b/tools/test_dependencies.py @@ -0,0 +1,47 @@ +#!/usr/bin/env python3 +"""Regression coverage for provider/client compatibility interval checks.""" +import plistlib +import tempfile +import unittest +from pathlib import Path +from kext_dependencies import check_dependencies + + +class DependencyTests(unittest.TestCase): + def check(self, minimum='0.5.0', requested='0.5.0', include_provider=True): + with tempfile.TemporaryDirectory() as tmp: + root = Path(tmp) + provider = {'CFBundleIdentifier': 'org.b00t0x.AppleIntelTGLCompat', + 'CFBundleVersion': '0.6.0', 'OSBundleCompatibleVersion': minimum} + client = {'CFBundleIdentifier': 'com.apple.driver.AppleIntelTGLGraphicsFramebuffer', + 'OSBundleLibraries': {'org.b00t0x.AppleIntelTGLCompat': requested, + 'com.apple.kpi.iokit': '10.0.0'}} + entries = [client, provider] if include_provider else [client] + paths = [] + for index, entry in enumerate(entries): + path = root / f'{index}.plist' + path.write_bytes(plistlib.dumps(entry)) + paths.append(path) + return check_dependencies(paths, 'test') + + def test_released_030_mismatch(self): + with self.assertRaisesRegex(ValueError, 'outside provider compatibility range'): + self.check(minimum='0.6.0') + + def test_compatible_lower_boundary(self): + self.assertEqual(self.check(), 1) + + def test_current_upper_boundary(self): + self.assertEqual(self.check(requested='0.6.0'), 1) + + def test_future_requirement(self): + with self.assertRaisesRegex(ValueError, 'outside provider compatibility range'): + self.check(requested='0.7.0') + + def test_missing_provider(self): + with self.assertRaisesRegex(ValueError, 'missing provider'): + self.check(include_provider=False) + + +if __name__ == '__main__': + unittest.main() diff --git a/tools/verify.py b/tools/verify.py index b157b30..4653139 100644 --- a/tools/verify.py +++ b/tools/verify.py @@ -6,6 +6,7 @@ import plistlib import subprocess from pathlib import Path +from kext_dependencies import check_dependencies ROOT = Path(__file__).resolve().parents[1] MOD_LEAF = '6de7fc5377deac4f5fe21194684f57f553c3592c' @@ -21,6 +22,11 @@ def main(): parser = argparse.ArgumentParser(description=__doc__) parser.add_argument('--rcodesign', default='rcodesign') args = parser.parse_args() + policy = json.loads((ROOT / 'tools/policy.json').read_text()) + common = list((ROOT / 'payloads/Common/Library/Extensions').glob('*.kext/Contents/Info.plist')) + for system in policy['systems']: + clients = list((ROOT / 'payloads' / system['payload'] / 'Library/Extensions').glob('*.kext/Contents/Info.plist')) + assert check_dependencies(common + clients, system['name']) > 0 seen = set() for path in sorted((ROOT / 'payloads').rglob('*')): assert not path.is_symlink(), path @@ -61,6 +67,8 @@ def main(): path = ROOT / 'payloads' / os / 'Library/Extensions/AppleIntelTGLCompat.kext/Contents/MacOS/AppleIntelTGLCompat' assert hashlib.sha256(path.read_bytes()).hexdigest() == entry['sha256'], os info = plistlib.loads((path.parent.parent / 'Info.plist').read_bytes()) + assert info['CFBundleVersion'] == entry['version'] + assert info['OSBundleCompatibleVersion'] == entry['compatible_version'] assert hashlib.sha256(plistlib.dumps(info['IOKitPersonalities'])).hexdigest() == entry['policy_source_sha256'], os adapter = ROOT / 'payloads/Common/Library/GPUBundles/XeCompilerAdapter.bundle/Contents/MacOS/adapter.dylib' assert hashlib.sha256(adapter.read_bytes()).hexdigest() == expected['compiler_adapter']['sha256']