aboutsummaryrefslogtreecommitdiffstats
path: root/docs/design/check-abi-layout.py
diff options
context:
space:
mode:
authoreunhhu <[email protected]>2026-09-24 17:14:54 +0100
committereunhhu <[email protected]>2026-09-24 17:14:54 +0100
commitb1ce1927022d374198441afafeb27199fc8a052a (patch)
tree6021f175f4c67ed03b44240eaa2f90d846f12f6f /docs/design/check-abi-layout.py
parentd34f9426d5317a1948f12f229439946728bc342a (diff)
downloadpure-b1ce1927022d374198441afafeb27199fc8a052a.tar.gz
pure-b1ce1927022d374198441afafeb27199fc8a052a.zip
Establish native micro runtime checkpoint
Diffstat (limited to 'docs/design/check-abi-layout.py')
-rw-r--r--docs/design/check-abi-layout.py46
1 files changed, 46 insertions, 0 deletions
diff --git a/docs/design/check-abi-layout.py b/docs/design/check-abi-layout.py
new file mode 100644
index 0000000..7832aff
--- /dev/null
+++ b/docs/design/check-abi-layout.py
@@ -0,0 +1,46 @@
+#!/usr/bin/env python3
+"""Compile draft record assertions only; does not test a callable module ABI."""
+import argparse
+from datetime import datetime, timezone
+import hashlib
+import json
+import os
+from pathlib import Path
+import shutil
+import subprocess
+import tempfile
+
+root = Path(__file__).resolve().parent
+parser = argparse.ArgumentParser(description=__doc__)
+parser.add_argument('--zig', default='zig')
+parser.add_argument('--output', type=Path)
+args = parser.parse_args()
+zig = shutil.which(args.zig)
+if not zig:
+ parser.error('Zig 0.15.2 required; use --zig /path/to/zig')
+version = subprocess.check_output([zig, 'version'], text=True).strip()
+if version != '0.15.2':
+ parser.error(f'This check is pinned to Zig 0.15.2; found {version}')
+header = root / 'abi-v0.h'
+checks = []
+with tempfile.TemporaryDirectory(prefix='pure-abi-layout-') as cache:
+ env = dict(os.environ, ZIG_GLOBAL_CACHE_DIR=cache)
+ for target in ['aarch64-linux-gnu', 'aarch64-macos-none', 'wasm32-freestanding']:
+ command = [zig, 'cc', '-target', target, '-std=c17', '-ffreestanding',
+ '-Wall', '-Wextra', '-Werror', '-x', 'c', '-c', str(header),
+ '-o', str(Path(cache) / f'{target}.o')]
+ result = subprocess.run(command, env=env, capture_output=True, text=True)
+ checks.append({'target': target, 'command': command, 'exitCode': result.returncode,
+ 'stdout': result.stdout, 'stderr': result.stderr})
+report = {'recordedUtc': datetime.now(timezone.utc).isoformat(), 'zigVersion': version,
+ 'scope': 'Cross-compilation of C17 record sizes/offset assertions only. No target execution, function calls, module loading, memory enforcement, or performance measurement.',
+ 'headerSha256': hashlib.sha256(header.read_bytes()).hexdigest(),
+ 'checkerSha256': hashlib.sha256(Path(__file__).read_bytes()).hexdigest(),
+ 'assertionsPerTarget': 8, 'checks': checks,
+ 'passed': all(check['exitCode'] == 0 for check in checks)}
+encoded = json.dumps(report, indent=2) + '\n'
+if args.output:
+ with args.output.open('x') as stream:
+ stream.write(encoded)
+print(encoded, end='')
+raise SystemExit(0 if report['passed'] else 1)