0.1.0-0-pre.7
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
#!/usr/bin/env python3
|
||||
# file: scripts/audit_rust_general_rules.py
|
||||
# version: 1
|
||||
# version: 2
|
||||
|
||||
"""Audit mechanically verifiable Rust normalization rules used by games.sasedev."""
|
||||
|
||||
@@ -513,9 +513,18 @@ def audit_file(root: pathlib.Path, path: pathlib.Path) -> list[Violation]:
|
||||
violations.append(Violation("RUST-IMPORT-114", relative, current_idx, "module use block is not alphabetically ordered"))
|
||||
# Crate façade constraints.
|
||||
if path.name in {"lib.rs", "main.rs"}:
|
||||
for attribute in ("#![warn(missing_docs)]", "#![deny(unreachable_pub)]", "#![forbid(unsafe_code)]"):
|
||||
ffi_export_exception = relative == "crates/apps/game-android-entrypoint/src/lib.rs"
|
||||
required_attributes = ["#![warn(missing_docs)]", "#![deny(unreachable_pub)]"]
|
||||
required_attributes.append("#![allow(unsafe_code)]" if ffi_export_exception else "#![forbid(unsafe_code)]")
|
||||
for attribute in required_attributes:
|
||||
if attribute not in lines[:24]:
|
||||
violations.append(Violation("RUST-BASE-103", relative, 1, f"missing `{attribute}`"))
|
||||
if ffi_export_exception:
|
||||
export_attribute = '#[unsafe(export_name = "SDL_main")]'
|
||||
if text.count(export_attribute) != 1:
|
||||
violations.append(Violation("RUST-FFI-101", relative, 1, "Android entrypoint must contain exactly one SDL_main export attribute"))
|
||||
if "unsafe {" in text or re.search(r"\bunsafe\s+fn\b", text) is not None or re.search(r"\bunsafe\s+extern\b", text) is not None:
|
||||
violations.append(Violation("RUST-FFI-102", relative, 1, "Android entrypoint exception permits an unsafe export attribute only; unsafe blocks/functions remain forbidden"))
|
||||
exports: list[tuple[int, str]] = []
|
||||
for idx, line in enumerate(lines, 1):
|
||||
stripped = line.strip()
|
||||
|
||||
79
scripts/build_android_rust.py
Normal file
79
scripts/build_android_rust.py
Normal file
@@ -0,0 +1,79 @@
|
||||
#!/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())
|
||||
Reference in New Issue
Block a user