Files
games/scripts/build_android_rust.py
2026-09-16 09:29:19 +02:00

80 lines
3.1 KiB
Python

#!/usr/bin/env python3
# file: scripts/build_android_rust.py
# version: 1
"""Build one Android Rust game entrypoint and stage it as Gradle jniLibs."""
from __future__ import annotations
import argparse
import os
import pathlib
import subprocess
import sys
import zipfile
ABI_TO_TRIPLE = {
"arm64-v8a": "aarch64-linux-android",
"armeabi-v7a": "armv7-linux-androideabi",
"x86_64": "x86_64-linux-android",
"x86": "i686-linux-android",
}
GAME_TO_MODULE = {"reflex": "game-reflex-poc", "snake": "game-snake-poc"}
def read_sdl3_aar_name(properties_path: pathlib.Path) -> str:
"""Read the configured SDL3 AAR filename."""
for raw_line in properties_path.read_text(encoding="utf-8").splitlines():
line = raw_line.strip()
if line.startswith("sdl3AarName="):
return line.split("=", 1)[1].strip()
raise RuntimeError("sdl3AarName is missing from Android/gradle.properties")
def extract_sdl3_link_library(aar_path: pathlib.Path, abi: str, output_dir: pathlib.Path) -> pathlib.Path:
"""Extract the SDL3 shared library used only for the Rust linker search path."""
expected = f"jni/{abi}/libSDL3.so"
output_dir.mkdir(parents=True, exist_ok=True)
with zipfile.ZipFile(aar_path) as archive:
if expected not in archive.namelist():
raise RuntimeError(f"{expected} is missing from {aar_path}")
target = output_dir / "libSDL3.so"
target.write_bytes(archive.read(expected))
return target
def main() -> int:
"""Build the requested game entrypoint for one Android ABI."""
parser = argparse.ArgumentParser()
parser.add_argument("game", choices=sorted(GAME_TO_MODULE))
parser.add_argument("--abi", choices=sorted(ABI_TO_TRIPLE), default="arm64-v8a")
parser.add_argument("--release", action="store_true")
arguments = parser.parse_args()
root = pathlib.Path(__file__).resolve().parent.parent
aar_name = read_sdl3_aar_name(root / "Android" / "gradle.properties")
aar_path = root / "Android" / "libs" / aar_name
if not aar_path.is_file():
print(f"missing SDL3 AAR: {aar_path}", file=sys.stderr)
return 2
link_dir = root / "Android" / "build" / "rust-link" / arguments.abi
try:
extract_sdl3_link_library(aar_path, arguments.abi, link_dir)
except (OSError, RuntimeError, zipfile.BadZipFile) as error:
print(str(error), file=sys.stderr)
return 2
module = GAME_TO_MODULE[arguments.game]
output = root / "Android" / module / "src" / "main" / "jniLibs"
environment = os.environ.copy()
rustflags = environment.get("RUSTFLAGS", "").strip()
link_flag = f"-L native={link_dir}"
environment["RUSTFLAGS"] = f"{rustflags} {link_flag}".strip()
environment["CARGO_NDK_PLATFORM"] = "21"
command = [
"cargo", "ndk", "-t", arguments.abi, "-o", str(output), "build",
"-p", "game-android-entrypoint", "--no-default-features", "--features", arguments.game,
]
if arguments.release:
command.append("--release")
completed = subprocess.run(command, cwd=root, env=environment, check=False)
return completed.returncode
if __name__ == "__main__":
raise SystemExit(main())