#!/usr/bin/env python3
"""Ein Cross-Ziel auf dem Linux-arm64-Runner bauen und mit Hostwerkzeug paketieren."""
import argparse
import hashlib
import json
import os
from pathlib import Path
import platform
import subprocess
import distribution as dist


def main():
    parser = argparse.ArgumentParser(description=__doc__)
    parser.add_argument('--target', choices=dist.TARGETS, required=True)
    parser.add_argument('--output', type=Path, required=True)
    args = parser.parse_args()
    dist.require(platform.system() == 'Linux' and platform.machine() == 'aarch64', 'Buildhost muss Linux arm64 sein')
    target = args.target
    env = dict(os.environ, CARGO_BUILD_JOBS='2', MACOSX_DEPLOYMENT_TARGET='11.0',
               CARGO_TARGET_X86_64_PC_WINDOWS_MSVC_RUSTFLAGS='-C target-feature=+crt-static',
               XWIN_VERSION='17', XWIN_SDK_VERSION='10.0.26100', XWIN_CRT_VERSION='14.44.17.14')
    if target.endswith('msvc'):
        builder = ['cargo', 'xwin', 'build']
        build_target = target
    else:
        builder = ['cargo', 'zigbuild']
        build_target = target + ('.2.28' if target.endswith('linux-gnu') else '')
    dist.run(['rustup', 'target', 'add', target])
    dist.run(builder + ['--locked', '--release', '--target', build_target,
                        '-p', 'tb-ide', '-p', 'tb-cli', '-p', 'tb-runner', '--bins'], cwd=dist.ROOT, env=env)
    dist.run(['cargo', 'build', '--locked', '--release', '-p', 'tb-export', '--bin', 'tb-template'], cwd=dist.ROOT, env=env)
    cargo_target = Path(os.environ.get('CARGO_TARGET_DIR', dist.ROOT / 'target')).resolve()
    metadata = dict(builder=builder[1], build_target=build_target, macos_deployment='11.0')
    if target.endswith('msvc'):
        # Exakte Header/Library-Bytes pinnen; Microsoft-Kanäle können ihre
        # Pakete auch unter derselben SDK-/CRT-Bezeichnung aktualisieren.
        cache = Path.home() / '.cache/cargo-xwin/xwin'
        checksum = hashlib.sha256()
        for path in sorted(cache.rglob('*')):
            if path.relative_to(cache).parts[0] not in ('crt', 'sdk'):
                continue
            if path.is_file() or path.is_symlink():
                checksum.update(path.relative_to(cache).as_posix().encode() + b'\0')
                checksum.update((str(path.readlink()).encode() if path.is_symlink() else
                                 hashlib.sha256(path.read_bytes()).digest()) + b'\0')
        dist.require(checksum.hexdigest() == '622fb2c2e3560514bfd59b87114c2aea72c15514614e95d01ddae7def96de047',
                     'SDK-/CRT-Inhalt weicht vom geprüften Build ab; Pin bewusst aktualisieren')
        metadata.update(sdk='10.0.26100', crt='14.44.17.14', sdk_tree_sha256=checksum.hexdigest(), crt_static=True)
    os.environ['TB_BUILD_METADATA'] = json.dumps(metadata)
    dist.pack(cargo_target / target / 'release', target, args.output.resolve(), cargo_target / 'release/tb-template')
    # Abhängigkeiten und Build-Baselines offen ausweisen; das sind keine gemessenen Mindest-OS-Versionen.
    with (args.output / (dist.TARGETS[target][0] + '-build.txt')).open('w') as log:
        for command in (['uname', '-a'], ['rustc', '-vV'], ['cargo', '--version']):
            subprocess.run(command, stdout=log, stderr=subprocess.STDOUT, check=True)
        log.write(f'image={os.environ.get("TB_BUILD_IMAGE", "local")}\n'
                  f'build_target={build_target}\nMACOSX_DEPLOYMENT_TARGET=11.0\n'
                  'XWIN_VERSION=17\nXWIN_SDK_VERSION=10.0.26100\nXWIN_CRT_VERSION=14.44.17.14\n')


if __name__ == '__main__':
    main()
