| 1 | #!/usr/bin/env python3 |
| 2 | """Builds snowbound-relay, the Live Share relay, and snowbound-site, which serves the web build and |
| 3 | the codes' pages (crates/relay), as static executables for each Linux architecture a server |
| 4 | runs, with the files that deploy them, into target/relay/ by default. |
| 5 | It ships on its own, outside the app's builds and latest.json; see crates/relay/README.md.""" |
| 6 | import argparse |
| 7 | import hashlib |
| 8 | import os |
| 9 | from pathlib import Path |
| 10 | import shutil |
| 11 | import subprocess |
| 12 | |
| 13 | from cargo_fresh import clean_local |
| 14 | |
| 15 | ROOT = Path(__file__).resolve().parents[1] |
| 16 | ARCHITECTURES = ['x86_64', 'aarch64'] |
| 17 | |
| 18 | |
| 19 | def build(arch, output): |
| 20 | """Linked against Rust's own musl by its own lld, so the file needs nothing of the Linux it |
| 21 | runs on.""" |
| 22 | triple = f'{arch}-unknown-linux-musl' |
| 23 | subprocess.run(['rustup', 'target', 'add', triple], check=True, capture_output=True) |
| 24 | environment = {**os.environ, f'CARGO_TARGET_{triple.upper().replace("-", "_")}_LINKER': 'rust-lld', |
| 25 | 'CARGO_PROFILE_RELEASE_STRIP': 'symbols'} |
| 26 | clean_local(ROOT, '--release', '--target', triple, environment=environment) |
| 27 | subprocess.run(['cargo', 'build', '--locked', '--release', '-p', 'relay', '--target', triple], |
| 28 | cwd=ROOT, env=environment, check=True) |
| 29 | target = Path(os.environ.get('CARGO_TARGET_DIR') or ROOT / 'target') |
| 30 | files = [] |
| 31 | for name in ['snowbound-relay', 'snowbound-site']: |
| 32 | file = output / f'{name}-linux-{arch}' |
| 33 | shutil.copy(target / triple / f'release/{name}', file) |
| 34 | files.append(file) |
| 35 | return files |
| 36 | |
| 37 | |
| 38 | def main(): |
| 39 | parser = argparse.ArgumentParser(description=__doc__) |
| 40 | parser.add_argument('--output', type=Path, default=ROOT / 'target/relay') |
| 41 | parser.add_argument('--architectures', nargs='+', choices=ARCHITECTURES, default=ARCHITECTURES) |
| 42 | args = parser.parse_args() |
| 43 | args.output.mkdir(parents=True, exist_ok=True) |
| 44 | files = [file for arch in args.architectures for file in build(arch, args.output)] |
| 45 | for deployed in (ROOT / 'crates/relay/deploy').iterdir(): |
| 46 | shutil.copy(deployed, args.output) |
| 47 | shutil.copy(ROOT / 'crates/relay/README.md', args.output) |
| 48 | sums = ''.join(f'{hashlib.sha256(file.read_bytes()).hexdigest()} {file.name}\n' for file in files) |
| 49 | (args.output / 'SHA256SUMS').write_text(sums) |
| 50 | print(f'{args.output}:\n{sums}', end='') |
| 51 | |
| 52 | |
| 53 | if __name__ == '__main__': |
| 54 | main() |