mirror of
https://github.com/okhsunrog/vpnhide.git
synced 2026-07-25 00:43:53 +00:00
103 lines
3.5 KiB
Python
Executable file
103 lines
3.5 KiB
Python
Executable file
#!/usr/bin/env python3
|
||
"""Build the vpnhide KPM and package it as an installable KernelSU/Magisk
|
||
module zip — single entry point for CI and local builds.
|
||
|
||
The `.kpm` is one cross-version relocatable object (it loads on every kernel
|
||
3.18–6.12 and on both KernelPatch runtimes), so unlike the `.ko` there is no
|
||
per-KMI matrix: one build, one zip.
|
||
|
||
Build step: `make -C kmod kpm` (host clang, no kernel tree — only the
|
||
KernelPatch submodule headers). Set CLANG_DIR to pick a specific clang;
|
||
otherwise `clang` from PATH is used (must bundle lld for the `-r` link).
|
||
|
||
Output: vpnhide-kpm.zip at the repo root (override with --out).
|
||
|
||
./kmod/kpm/build.py
|
||
CLANG_DIR=/opt/ddk/clang/clang-r*/bin ./kmod/kpm/build.py
|
||
"""
|
||
|
||
from __future__ import annotations
|
||
|
||
import argparse
|
||
import os
|
||
import re
|
||
import shutil
|
||
import subprocess
|
||
import sys
|
||
from pathlib import Path
|
||
|
||
sys.path.insert(0, str(Path(__file__).resolve().parent.parent.parent / "scripts"))
|
||
from build_lib import ( # type: ignore[import-not-found]
|
||
build_activator_bin,
|
||
get_build_version,
|
||
make_zip,
|
||
)
|
||
|
||
KPM_FILE = "vpnhide.kpm"
|
||
|
||
|
||
def main() -> int:
|
||
parser = argparse.ArgumentParser(description="Build the vpnhide KPM module zip.")
|
||
parser.add_argument(
|
||
"--out",
|
||
type=Path,
|
||
help="Output zip path. Default: vpnhide-kpm.zip in the repo root.",
|
||
)
|
||
args = parser.parse_args()
|
||
|
||
kpm_dir = Path(__file__).resolve().parent
|
||
kmod_dir = kpm_dir.parent
|
||
repo_root = kmod_dir.parent
|
||
activator = build_activator_bin(repo_root, "kpm")
|
||
|
||
# Build the .kpm. `make` decides whether anything needs rebuilding; pass
|
||
# CLANG_DIR through if the caller set it (CI / direnv .env).
|
||
make_cmd = ["make", "-C", str(kmod_dir), "kpm"]
|
||
clang_dir = os.environ.get("CLANG_DIR")
|
||
if clang_dir:
|
||
make_cmd.append(f"CLANG_DIR={clang_dir}")
|
||
subprocess.run(make_cmd, check=True)
|
||
|
||
kpm_src = kmod_dir / KPM_FILE
|
||
if not kpm_src.exists():
|
||
print(f"error: expected {kpm_src} after `make kpm`, not found", file=sys.stderr)
|
||
return 1
|
||
|
||
# Stage the module skeleton, drop the freshly built .kpm in.
|
||
staging = kpm_dir / "module-staging"
|
||
if staging.exists():
|
||
shutil.rmtree(staging)
|
||
shutil.copytree(kpm_dir / "module", staging)
|
||
shutil.copy(kpm_src, staging / KPM_FILE)
|
||
shutil.copy(activator, staging / "activator")
|
||
(staging / "activator").chmod(0o755)
|
||
|
||
# Stamp the effective build version into the staged module.prop without
|
||
# touching the committed file (keeps PR diffs from churning it).
|
||
build_version = get_build_version(repo_root)
|
||
module_prop = staging / "module.prop"
|
||
content = module_prop.read_text(encoding="utf-8")
|
||
content = re.sub(r"^version=.*", f"version=v{build_version}", content, flags=re.MULTILINE)
|
||
module_prop.write_text(content, encoding="utf-8")
|
||
print(f"stamped module.prop version=v{build_version}")
|
||
|
||
# CI sets UPDATE_JSON_URL so Magisk/KSU knows where to check for updates;
|
||
# local dev builds leave it unset and ship without updateJson.
|
||
update_json_url = os.environ.get("UPDATE_JSON_URL")
|
||
if update_json_url:
|
||
with module_prop.open("a", encoding="utf-8") as f:
|
||
f.write(f"updateJson={update_json_url}\n")
|
||
|
||
out_zip = args.out if args.out else repo_root / "vpnhide-kpm.zip"
|
||
if out_zip.exists():
|
||
out_zip.unlink()
|
||
make_zip(staging, out_zip)
|
||
shutil.rmtree(staging)
|
||
|
||
size_kb = out_zip.stat().st_size / 1024
|
||
print(f"built {out_zip} ({size_kb:.1f} KB)")
|
||
return 0
|
||
|
||
|
||
if __name__ == "__main__":
|
||
sys.exit(main())
|