1#!/usr/bin/env python3
2"""Builds snowbound-relay, the Live Share relay, and snowbound-site, which serves the web build and
3the codes' pages (crates/relay), as static executables for each Linux architecture a server
4runs, with the files that deploy them, into target/relay/ by default.
5It ships on its own, outside the app's builds and latest.json; see crates/relay/README.md."""
6import argparse
7import hashlib
8import os
9from pathlib import Path
10import shutil
11import subprocess
12
13from cargo_fresh import clean_local
14
15ROOT = Path(__file__).resolve().parents[1]
16ARCHITECTURES = ['x86_64', 'aarch64']
17
18
19def 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
38def 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
53if __name__ == '__main__':
54 main()