Compare commits

..
2 Commits
Author SHA1 Message Date
yyc12345 8098216a83 feat: finish packer cli (may changed in future 2026-08-01 22:39:55 +08:00
yyc12345 8e92ceeabd feat: create omrf packer basic layout 2026-08-01 22:31:39 +08:00
11 changed files with 159 additions and 7 deletions
-6
View File
@@ -1,6 +0,0 @@
def main():
print("Hello from sarasacw-omrf-packer!")
if __name__ == "__main__":
main()
+10
View File
@@ -3,7 +3,17 @@ name = "sarasacw-omrf-packer"
version = "0.1.0"
description = "Add your description here"
readme = "README.md"
authors = [
{ name = "yyc12345", email = "yyc12321@outlook.com" }
]
requires-python = ">=3.13"
dependencies = [
"jinja2==3.1.6",
]
[project.scripts]
sarasacw-omrf-packer = "sarasacw_omrf_packer:main"
[build-system]
requires = ["uv_build>=0.8.0,<0.9"]
build-backend = "uv_build"
@@ -0,0 +1,13 @@
from .archiver import pack
from .cargo import get_artifacts
from .cli import Cli, parse
from .cmake import render as render_cmake
from .pkgconfig import render as render_pkgconfig
def main() -> None:
cli = parse()
get_artifacts(cli.manifest_path)
render_cmake(cli.output_dir)
render_pkgconfig(cli.output_dir)
pack(cli.output_dir, cli.output_dir + ".zip")
@@ -0,0 +1,10 @@
import zipfile
from pathlib import Path
def pack(dist_dir: str, output_zip: str) -> None:
dist = Path(dist_dir)
with zipfile.ZipFile(output_zip, "w", zipfile.ZIP_DEFLATED) as zf:
for path in dist.rglob("*"):
if path.is_file():
zf.write(path, path.relative_to(dist))
+22
View File
@@ -0,0 +1,22 @@
import json
import subprocess
def get_metadata(manifest_path: str) -> dict:
cmd = [
"cargo",
"metadata",
"--format-version=1",
f"--manifest-path={manifest_path}",
]
proc = subprocess.Popen(
cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE
)
stdout, _ = proc.communicate()
return json.loads(stdout)
def get_artifacts(manifest_path: str) -> list[str]:
metadata = get_metadata(manifest_path)
target_directory = metadata["target_directory"]
return [target_directory]
+77
View File
@@ -0,0 +1,77 @@
import argparse
from dataclasses import dataclass
from pathlib import Path
@dataclass(frozen=True)
class Cli:
"""Captured command-line options for the packer.
Instances are immutable and are produced only by :func:`parse`; every
downstream stage of the pipeline reads its configuration from this object
rather than re-interpreting the command line.
"""
manifest: Path
"""Path to the ``Cargo.toml`` manifest of the project being packed."""
dist_dir: Path | None
"""Destination directory for the distributable layout, or ``None`` when
no on-disk distribution tree is requested."""
dist_zip: Path | None
"""Destination of the zip archive bundling the distribution tree, or
``None`` when no archive is requested."""
def parse() -> Cli:
"""Parse command-line arguments into a :class:`Cli` instance.
Builds an :class:`argparse.ArgumentParser`, interprets ``sys.argv`` and
returns the captured options as an immutable :class:`Cli`. The process is
terminated by argparse itself on error or when ``-h/--help`` is given.
"""
parser = argparse.ArgumentParser(
prog="SarasaCW OMRF Packer",
description=(
"Packaging tool of Sarasas Chip Workshop Oh My Rust FFI (OMRF). "
"Creates a CMake-style distributable layout and generates CMake "
"and pkg-config files for Rust FFI build artifacts."
),
)
parser.add_argument(
"-m",
"--manifest",
dest="manifest",
action="store",
type=Path,
required=True,
help="Path to the Cargo.toml manifest of the project to pack",
metavar="CARGO.TOML",
)
parser.add_argument(
"-d",
"--dist-dir",
dest="dist_dir",
action="store",
type=Path,
required=False,
help="Directory where distributable files are installed (creates a CMake layout: bin/, include/, lib/ ...)",
metavar="DIR",
)
parser.add_argument(
"-z",
"--dist-zip",
dest="dist_zip",
action="store",
type=Path,
required=False,
help="Path of the zip archive created from the dist-dir contents",
metavar="ZIP",
)
args = parser.parse_args()
return Cli(
manifest=args.manifest,
dist_dir=args.dist_dir,
dist_zip=args.dist_zip,
)
+13
View File
@@ -0,0 +1,13 @@
from pathlib import Path
from jinja2 import Environment, FileSystemLoader, select_autoescape
def render(output_dir: str) -> None:
templates_dir = Path(__file__).parent / "templates"
env = Environment(
loader=FileSystemLoader(templates_dir),
autoescape=select_autoescape(),
)
out = Path(output_dir)
out.mkdir(parents=True, exist_ok=True)
@@ -0,0 +1,13 @@
from pathlib import Path
from jinja2 import Environment, FileSystemLoader, select_autoescape
def render(output_dir: str) -> None:
templates_dir = Path(__file__).parent / "templates"
env = Environment(
loader=FileSystemLoader(templates_dir),
autoescape=select_autoescape(),
)
out = Path(output_dir)
out.mkdir(parents=True, exist_ok=True)
+1 -1
View File
@@ -69,7 +69,7 @@ wheels = [
[[package]]
name = "sarasacw-omrf-packer"
version = "0.1.0"
source = { virtual = "." }
source = { editable = "." }
dependencies = [
{ name = "jinja2" },
]