mirror of
https://github.com/valentderah/totk-pc-recomp.git
synced 2026-11-12 18:31:05 +00:00
The MacNativeGames BKTR and title-key changes and our UTF-8 manifest lived only in the maintainer's toolchain folder, so nobody else could build the hactool that extraction and the installer need. The script's exe matches the one in use byte for byte apart from its build time. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
76 lines
3.3 KiB
Python
76 lines
3.3 KiB
Python
"""Build hactool: toolchain/hactool/hactool.exe (SciresM/hactool at a pinned commit + tools/hactool/*.patch).
|
|
|
|
Fetches the pinned commit into toolchain/src/hactool, resets it (local changes and build output there are discarded),
|
|
applies portable.patch (MacNativeGames' Windows-relevant changes) and unicode.patch (ours), and builds a static exe
|
|
with MSYS2 UCRT64 gcc; mbedtls comes with hactool's tree. The exe and hactool's LICENSE go to toolchain/hactool, where
|
|
tools/extract.py and tools/make_release.py take them. Run with .venv.
|
|
|
|
python tools/build_hactool.py [--src DIR] [--out DIR]
|
|
"""
|
|
|
|
import argparse
|
|
import os
|
|
import shutil
|
|
import subprocess
|
|
import sys
|
|
from pathlib import Path
|
|
|
|
ROOT = Path(__file__).resolve().parent.parent
|
|
URL = 'https://github.com/SciresM/hactool.git'
|
|
COMMIT = '1d64a83450e025622f3468c28fc4164dad2c5ef6'
|
|
PATCHES = [ROOT / 'tools' / 'hactool' / n for n in ('portable.patch', 'unicode.patch')]
|
|
MSYS_BASH = Path(r'C:\msys64\usr\bin\bash.exe')
|
|
CONFIG_MK = ('CC = gcc\nEXEEXT = .exe\nCFLAGS = -O2 -Wall -Wextra -pedantic -std=gnu11\n'
|
|
'LDFLAGS = -lmbedtls -lmbedx509 -lmbedcrypto -static\n')
|
|
|
|
|
|
def git(src, *args):
|
|
subprocess.run(['git', '-C', str(src), *args], check=True)
|
|
|
|
|
|
def fetch(src):
|
|
"""src holds COMMIT with no local changes or untracked files."""
|
|
if not (src / '.git').is_dir():
|
|
src.mkdir(parents=True, exist_ok=True)
|
|
git(src, 'init', '-q')
|
|
git(src, 'remote', 'add', 'origin', URL)
|
|
head = subprocess.run(['git', '-C', str(src), 'rev-parse', 'HEAD'], capture_output=True, text=True).stdout.strip()
|
|
if head != COMMIT:
|
|
git(src, 'fetch', '-q', '--depth', '1', 'origin', COMMIT)
|
|
git(src, 'checkout', '-q', '-f', COMMIT)
|
|
git(src, 'clean', '-q', '-fdx')
|
|
|
|
|
|
def main():
|
|
ap = argparse.ArgumentParser(description=__doc__.splitlines()[0])
|
|
ap.add_argument('--src', type=Path, default=ROOT / 'toolchain' / 'src' / 'hactool', help='source checkout')
|
|
ap.add_argument('--out', type=Path, default=ROOT / 'toolchain' / 'hactool', help='where hactool.exe goes')
|
|
args = ap.parse_args()
|
|
if not MSYS_BASH.is_file():
|
|
sys.exit(f'{MSYS_BASH} not found: install MSYS2 with the UCRT64 gcc and make (docs/building.md)')
|
|
src, out = args.src.resolve(), args.out.resolve()
|
|
|
|
fetch(src)
|
|
for p in PATCHES:
|
|
git(src, 'apply', '--whitespace=nowarn', str(p))
|
|
(src / 'config.mk').write_text(CONFIG_MK, encoding='utf-8', newline='\n')
|
|
|
|
env = dict(os.environ, MSYSTEM='UCRT64', CHERE_INVOKING='1')
|
|
r = subprocess.run([str(MSYS_BASH), '-lc', f'make -j{os.cpu_count() or 4}'], cwd=src, env=env,
|
|
capture_output=True, text=True)
|
|
(src / 'build.log').write_text(r.stdout + r.stderr, encoding='utf-8')
|
|
if r.returncode:
|
|
sys.exit(f'make failed ({r.returncode}); log: {src / "build.log"}')
|
|
|
|
out.mkdir(parents=True, exist_ok=True)
|
|
shutil.copy2(src / 'hactool.exe', out / 'hactool.exe')
|
|
shutil.copy2(src / 'LICENSE', out / 'LICENSE')
|
|
banner = subprocess.run([str(out / 'hactool.exe')], capture_output=True, text=True)
|
|
if 'hactool (c) SciresM' not in banner.stdout + banner.stderr:
|
|
sys.exit(f'{out / "hactool.exe"} does not start')
|
|
print(f'{out / "hactool.exe"}: {COMMIT[:7]} + {", ".join(p.name for p in PATCHES)}')
|
|
|
|
|
|
if __name__ == '__main__':
|
|
main()
|