Add: just commands for release build

This commit is contained in:
DaZuo0122
2026-02-13 11:22:46 +08:00
parent 3c3ca342c9
commit 55fe53235d
21 changed files with 253 additions and 97 deletions

View File

@@ -1,5 +1,5 @@
#!/usr/bin/env python3
"""Build and package a portable Windows ZIP for sprimo-app."""
"""Build and package portable Windows ZIPs for Bevy/Tauri frontends."""
from __future__ import annotations
@@ -18,7 +18,6 @@ from typing import Iterable
ROOT = Path(__file__).resolve().parents[1]
DIST = ROOT / "dist"
BIN_REL = ROOT / "target" / "release" / "sprimo-app.exe"
ASSETS_REL = ROOT / "assets"
@@ -26,8 +25,36 @@ class PackagingError(RuntimeError):
"""Raised when packaging preconditions are not met."""
@dataclass(frozen=True)
class FrontendLayout:
id: str
crate: str
binary_name: str
artifact_name: str
readme_run: str
FRONTENDS: dict[str, FrontendLayout] = {
"bevy": FrontendLayout(
id="bevy",
crate="sprimo-app",
binary_name="sprimo-app.exe",
artifact_name="sprimo-windows-x64",
readme_run="sprimo-app.exe",
),
"tauri": FrontendLayout(
id="tauri",
crate="sprimo-tauri",
binary_name="sprimo-tauri.exe",
artifact_name="sprimo-tauri-windows-x64",
readme_run="sprimo-tauri.exe",
),
}
@dataclass(frozen=True)
class PackageLayout:
frontend: str
version: str
zip_path: Path
checksum_path: Path
@@ -72,12 +99,13 @@ def read_version() -> str:
raise PackagingError("could not determine version")
def ensure_release_binary() -> Path:
if not BIN_REL.exists():
run(["cargo", "build", "--release", "-p", "sprimo-app"])
if not BIN_REL.exists():
raise PackagingError(f"release binary missing: {BIN_REL}")
return BIN_REL
def ensure_release_binary(frontend: FrontendLayout) -> Path:
binary_path = ROOT / "target" / "release" / frontend.binary_name
if not binary_path.exists():
run(["cargo", "build", "--release", "-p", frontend.crate])
if not binary_path.exists():
raise PackagingError(f"release binary missing: {binary_path}")
return binary_path
def ensure_assets() -> None:
@@ -108,13 +136,13 @@ def sha256_file(path: Path) -> str:
return digest.hexdigest()
def package() -> PackageLayout:
def package(frontend: FrontendLayout) -> PackageLayout:
version = read_version()
ensure_assets()
binary = ensure_release_binary()
binary = ensure_release_binary(frontend)
DIST.mkdir(parents=True, exist_ok=True)
artifact_name = f"sprimo-windows-x64-v{version}"
artifact_name = f"{frontend.artifact_name}-v{version}"
zip_path = DIST / f"{artifact_name}.zip"
checksum_path = DIST / f"{artifact_name}.zip.sha256"
@@ -122,13 +150,14 @@ def package() -> PackageLayout:
stage = Path(temp_dir) / artifact_name
stage.mkdir(parents=True, exist_ok=True)
shutil.copy2(binary, stage / "sprimo-app.exe")
shutil.copy2(binary, stage / frontend.binary_name)
shutil.copytree(ASSETS_REL, stage / "assets", dirs_exist_ok=True)
readme = stage / "README.txt"
readme.write_text(
"Sprimo portable package\n"
"Run: sprimo-app.exe\n"
f"Frontend: {frontend.id}\n"
f"Run: {frontend.readme_run}\n"
"Assets are expected at ./assets relative to the executable.\n",
encoding="utf-8",
)
@@ -143,11 +172,16 @@ def package() -> PackageLayout:
checksum = sha256_file(zip_path)
checksum_path.write_text(f"{checksum} {zip_path.name}\n", encoding="utf-8")
return PackageLayout(version=version, zip_path=zip_path, checksum_path=checksum_path)
return PackageLayout(
frontend=frontend.id,
version=version,
zip_path=zip_path,
checksum_path=checksum_path,
)
def smoke() -> None:
layout = package()
def smoke(frontend: FrontendLayout) -> None:
layout = package(frontend)
print(f"package created: {layout.zip_path}")
print(f"checksum file: {layout.checksum_path}")
@@ -160,7 +194,7 @@ def smoke() -> None:
pkg_root = root_candidates[0]
required = [
pkg_root / "sprimo-app.exe",
pkg_root / frontend.binary_name,
pkg_root / "assets" / "sprite-packs" / "default" / "manifest.json",
pkg_root / "assets" / "sprite-packs" / "default" / "sprite.png",
]
@@ -175,18 +209,25 @@ def smoke() -> None:
def parse_args() -> argparse.Namespace:
parser = argparse.ArgumentParser(description="Sprimo Windows packaging helper")
parser.add_argument("command", choices=["package", "smoke"], help="action to execute")
parser.add_argument(
"--frontend",
choices=sorted(FRONTENDS.keys()),
default="bevy",
help="frontend package target",
)
return parser.parse_args()
def main() -> int:
args = parse_args()
frontend = FRONTENDS[args.frontend]
try:
if args.command == "package":
layout = package()
layout = package(frontend)
print(f"created: {layout.zip_path}")
print(f"sha256: {layout.checksum_path}")
else:
smoke()
smoke(frontend)
return 0
except PackagingError as exc:
print(f"error: {exc}", file=sys.stderr)