Run the original macOS ARM64 game code on iOS: - tools/retarget.py: header-only Mach-O retargeting to an iOS dylib - platform/native: UIKit host and macOS API shims (AppKit for SDL's Cocoa backend, CoreGraphics displays, CoreAudio device, Metal device properties, Wuffs PNG decoding, Steam and peripheral stubs) - touch, overlay, iOS keyboard and hardware keyboard input - tools/build_native.py: build, sign, install, data copy, launch - docs: build guide, controls, architecture Also includes the earlier static-translation research (ARM64 -> WASM -> native) under docs/research, runtime/, tests/ and tools/. No game files are included; the build reads them from a local install.
64 lines
3.3 KiB
Python
64 lines
3.3 KiB
Python
#!/usr/bin/env python3
|
|
"""Build and validate the bounded Factorio RNG no-JIT prototype on Apple Silicon."""
|
|
import argparse
|
|
import json
|
|
import subprocess
|
|
from pathlib import Path
|
|
from lift_rng import generate
|
|
|
|
ROOT = Path(__file__).resolve().parent.parent
|
|
|
|
|
|
def run(*command):
|
|
print("+", " ".join(map(str, command)), flush=True)
|
|
subprocess.run(list(map(str, command)), cwd=ROOT, check=True)
|
|
|
|
|
|
def main():
|
|
parser = argparse.ArgumentParser(description=__doc__)
|
|
parser.add_argument("binary", type=Path)
|
|
args = parser.parse_args()
|
|
wabt = ROOT / "third_party/wabt"
|
|
if not (wabt / "CMakeLists.txt").exists():
|
|
parser.error("Fetch official WABT tag 1.0.42 into third_party/wabt first")
|
|
revision = subprocess.check_output(["git", "-C", str(wabt), "rev-parse", "HEAD"], text=True).strip()
|
|
if revision != "ff0ef7e0009402740c805a9744c09b05be063e48":
|
|
parser.error("WABT checkout must match the pinned 1.0.42 commit")
|
|
run("cmake", "-S", wabt, "-B", ROOT / "build/wabt", "-DCMAKE_BUILD_TYPE=Release",
|
|
"-DBUILD_TESTS=OFF", "-DBUILD_LIBWASM=OFF", "-DUSE_INTERNAL_SHA256=ON",
|
|
"-DHAVE_OPENSSL_SHA_H=OFF")
|
|
run("cmake", "--build", ROOT / "build/wabt", "--target", "wat2wasm", "wasm2c", "--parallel", "6")
|
|
out = ROOT / "build/rng"
|
|
generate(args.binary.resolve(), out)
|
|
run(ROOT / "build/wabt/wat2wasm", out / "factorio_rng.wat", "-o", out / "factorio_rng.wasm")
|
|
run(ROOT / "build/wabt/wasm2c", out / "factorio_rng.wasm", "-o", out / "factorio_rng.c", "--module-name=factorio_rng")
|
|
sources = [out / "factorio_rng.c", wabt / "wasm2c/wasm-rt-impl.c", wabt / "wasm2c/wasm-rt-mem-impl.c"]
|
|
includes = ["-I" + str(out), "-I" + str(wabt / "wasm2c")]
|
|
flags = ["-O2", "-DWASM_RT_USE_MMAP=0", "-DWASM_RT_MEMCHECK_BOUNDS_CHECK=1"]
|
|
run("xcrun", "clang", *flags, *includes, *sources, out / "oracle.S", ROOT / "tests/rng_equivalence.c",
|
|
"-o", out / "verify_rng")
|
|
run(out / "verify_rng")
|
|
# This archive contains the translated function and wasm2c runtime only.
|
|
# The native oracle is a desktop verification input, never iOS runtime code.
|
|
objects = []
|
|
sdk = subprocess.check_output(["xcrun", "--sdk", "iphoneos", "--show-sdk-path"], text=True).strip()
|
|
for source in sources:
|
|
obj = out / (source.stem + ".ios.o")
|
|
run("xcrun", "--sdk", "iphoneos", "clang", "-target", "arm64-apple-ios15.0", "-isysroot", sdk,
|
|
*flags, *includes, "-c", source, "-o", obj)
|
|
objects.append(obj)
|
|
run("xcrun", "libtool", "-static", "-o", out / "libfactorio_rng_ios.a", *objects)
|
|
undefined = subprocess.check_output(["xcrun", "nm", "-u", str(out / "libfactorio_rng_ios.a")], text=True)
|
|
if "steam" in undefined.lower():
|
|
raise RuntimeError("Steam import found in the single-player port library")
|
|
report = {"status": "pass", "native_comparisons": 876544, "constructor_comparisons": 1024, "starting_states": 6848,
|
|
"steps_per_state": 128, "ios_artifact": "libfactorio_rng_ios.a",
|
|
"ios_device_execution": "not run", "full_game": "not implemented",
|
|
"wabt_commit": revision, "runtime_jit": False,
|
|
"steam_import_audit": "pass: no Steam undefined symbols"}
|
|
(out / "verification.json").write_text(json.dumps(report, indent=2) + "\n")
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|