0.3.3-0-pre.5
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
#!/usr/bin/env python3
|
||||
# file: scripts/audit_distribution_layout.py
|
||||
# version: 16
|
||||
# version: 17
|
||||
|
||||
"""Audit the static distribution layout expected by supported POCs."""
|
||||
|
||||
@@ -17,6 +17,9 @@ FORBIDDEN_PATHS = (
|
||||
"Android/gradlew.bat",
|
||||
"Android/gradle/wrapper/gradle-wrapper.jar",
|
||||
"Android/gradle/wrapper/gradle-wrapper.properties",
|
||||
"Android/game-reflex-poc/src/main/jniLibs",
|
||||
"Android/game-snake-poc/src/main/jniLibs",
|
||||
"scripts/build_android_rust.py",
|
||||
)
|
||||
|
||||
|
||||
@@ -66,7 +69,6 @@ REQUIRED_PATHS = (
|
||||
"Android/game-snake-poc/build.gradle",
|
||||
"Android/settings.gradle",
|
||||
"Android/gradle/sasedev-rust-android.gradle",
|
||||
"scripts/build_android_rust.py",
|
||||
"scripts/build_reflex_tauri_wasm.py",
|
||||
"assets/common",
|
||||
"assets/game-reflex-poc",
|
||||
@@ -334,9 +336,12 @@ def audit_android_native_gradle(root: pathlib.Path) -> list[str]:
|
||||
|
||||
native_script = native_script_path.read_text(encoding="utf-8")
|
||||
native_fragments = (
|
||||
'spec.commandLine(',
|
||||
'spec.commandLine(cargoCommand)',
|
||||
'"cargo",',
|
||||
'"ndk",',
|
||||
'cargoCommand.add("--release")',
|
||||
'releaseBuild.set(selectedReleaseBuild)',
|
||||
'onVariants(selector().all())',
|
||||
'"--no-default-features",',
|
||||
'variant.sources.jniLibs.addGeneratedSourceDirectory',
|
||||
'generated/sasedevNative/',
|
||||
@@ -363,6 +368,8 @@ def audit_android_native_gradle(root: pathlib.Path) -> list[str]:
|
||||
)
|
||||
shared_fragments = (
|
||||
'ext.sasedevRustAndroidAbis = ["arm64-v8a", "armeabi-v7a", "x86_64", "x86"]',
|
||||
'ext.sasedevRustAndroidApi = 21',
|
||||
'minSdk 21',
|
||||
"abiFilters 'arm64-v8a', 'armeabi-v7a', 'x86_64', 'x86'",
|
||||
'apply from: rootProject.file("gradle/sasedev-rust-android.gradle")',
|
||||
)
|
||||
|
||||
@@ -1,139 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
# file: scripts/build_android_rust.py
|
||||
# version: 3
|
||||
|
||||
"""Build one Android Rust game entrypoint and stage SDL3 and Rust jniLibs."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import argparse
|
||||
import os
|
||||
import pathlib
|
||||
import shutil
|
||||
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_gradle_property(properties_path: pathlib.Path, property_name: str) -> str:
|
||||
"""Read one required Android Gradle property."""
|
||||
prefix = f"{property_name}="
|
||||
for raw_line in properties_path.read_text(encoding="utf-8").splitlines():
|
||||
line = raw_line.strip()
|
||||
if line.startswith(prefix):
|
||||
return line.split("=", 1)[1].strip()
|
||||
raise RuntimeError(f"{property_name} is missing from Android/gradle.properties")
|
||||
|
||||
def read_sdl3_aar_name(properties_path: pathlib.Path) -> str:
|
||||
"""Read the configured SDL3 AAR filename."""
|
||||
return read_gradle_property(properties_path, "sdl3AarName")
|
||||
|
||||
def find_sdl3_member(archive: zipfile.ZipFile, abi: str) -> str:
|
||||
"""Return the SDL3 shared-library member for one Android ABI."""
|
||||
candidates = (
|
||||
f"prefab/modules/SDL3/libs/android.{abi}/libSDL3.so",
|
||||
f"jni/{abi}/libSDL3.so",
|
||||
)
|
||||
members = set(archive.namelist())
|
||||
for candidate in candidates:
|
||||
if candidate in members:
|
||||
return candidate
|
||||
suffix = f"/libs/android.{abi}/libSDL3.so"
|
||||
fallback = sorted(member for member in members if member.endswith(suffix))
|
||||
if len(fallback) == 1:
|
||||
return fallback[0]
|
||||
raise RuntimeError(
|
||||
f"SDL3 shared library for ABI {abi} is missing from the AAR; "
|
||||
f"expected Prefab member {candidates[0]}"
|
||||
)
|
||||
|
||||
def extract_sdl3_library(
|
||||
aar_path: pathlib.Path,
|
||||
abi: str,
|
||||
link_dir: pathlib.Path,
|
||||
runtime_dir: pathlib.Path,
|
||||
) -> pathlib.Path:
|
||||
"""Extract SDL3 for both Rust linking and APK runtime staging."""
|
||||
link_dir.mkdir(parents=True, exist_ok=True)
|
||||
runtime_dir.mkdir(parents=True, exist_ok=True)
|
||||
with zipfile.ZipFile(aar_path) as archive:
|
||||
member = find_sdl3_member(archive, abi)
|
||||
payload = archive.read(member)
|
||||
link_target = link_dir / "libSDL3.so"
|
||||
runtime_target = runtime_dir / "libSDL3.so"
|
||||
link_target.write_bytes(payload)
|
||||
runtime_target.write_bytes(payload)
|
||||
return link_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
|
||||
properties_path = root / "Android" / "gradle.properties"
|
||||
aar_name = read_sdl3_aar_name(properties_path)
|
||||
ndk_version = read_gradle_property(properties_path, "androidNdkVersion")
|
||||
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
|
||||
module = GAME_TO_MODULE[arguments.game]
|
||||
jni_root = root / "Android" / module / "src" / "main" / "jniLibs"
|
||||
runtime_dir = jni_root / arguments.abi
|
||||
link_dir = root / "Android" / "build" / "rust-link" / arguments.abi
|
||||
try:
|
||||
extract_sdl3_library(aar_path, arguments.abi, link_dir, runtime_dir)
|
||||
except (OSError, RuntimeError, zipfile.BadZipFile) as error:
|
||||
print(str(error), file=sys.stderr)
|
||||
return 2
|
||||
environment = os.environ.copy()
|
||||
android_home = environment.get("ANDROID_HOME")
|
||||
if not android_home:
|
||||
print("ANDROID_HOME is required to resolve the project NDK", file=sys.stderr)
|
||||
return 2
|
||||
ndk_home = pathlib.Path(android_home) / "ndk" / ndk_version
|
||||
if not ndk_home.is_dir():
|
||||
print(f"configured Android NDK is missing: {ndk_home}", file=sys.stderr)
|
||||
return 2
|
||||
environment["ANDROID_NDK_HOME"] = str(ndk_home)
|
||||
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(jni_root),
|
||||
"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)
|
||||
if completed.returncode != 0:
|
||||
return completed.returncode
|
||||
expected = runtime_dir / "libgame_android_entrypoint.so"
|
||||
if not expected.is_file():
|
||||
print(f"missing Rust Android library after cargo-ndk build: {expected}", file=sys.stderr)
|
||||
return 3
|
||||
return 0
|
||||
|
||||
if __name__ == "__main__":
|
||||
raise SystemExit(main())
|
||||
Reference in New Issue
Block a user