diff options
| author | hachem <im@hachem.wtf> | 2026-09-06 06:21:52 +0200 |
|---|---|---|
| committer | hachem <im@hachem.wtf> | 2026-09-06 06:21:52 +0200 |
| commit | 392c49d61fec199605c9cff6e1e2975660e1b846 (patch) | |
| tree | ab77f5deee5aa993b9bc9224904845af3107203c /tools/fetch_llvm.py | |
| parent | 9a3a74070be2de9cd58f778e7a6d1df05cb60474 (diff) | |
feat: migrate over to meson
Diffstat (limited to 'tools/fetch_llvm.py')
| -rw-r--r-- | tools/fetch_llvm.py | 128 |
1 files changed, 128 insertions, 0 deletions
diff --git a/tools/fetch_llvm.py b/tools/fetch_llvm.py new file mode 100644 index 0000000..8a596a8 --- /dev/null +++ b/tools/fetch_llvm.py @@ -0,0 +1,128 @@ +#!/usr/bin/env python3 +# Download the pinned LLVM release and unpack it into ext/llvm, mirroring the old +# premake5.lua `fetch-llvm` action. Run this once before `meson setup` on a +# machine without a suitable LLVM install: +# +# python3 tools/fetch_llvm.py +# +# It is a no-op when ext/llvm already carries the LLDB headers. + +import os +import platform +import shutil +import sys +import tarfile +import urllib.request + +LLVM_VERSION = "22.1.0" + +REPO_ROOT = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) +EXT = os.path.join(REPO_ROOT, "ext") +VENDORED = os.path.join(EXT, "llvm") +STAGING = os.path.join(EXT, "llvm-staging") + + +def is_arm(): + machine = platform.machine().lower() + return machine in ("arm64", "aarch64") + + +def release_asset(): + host = platform.system() + + if host == "Darwin": + # LLVM only publishes an Apple-silicon macOS binary + return f"LLVM-{LLVM_VERSION}-macOS-ARM64.tar.xz" if is_arm() else None + + if host == "Linux": + arch = "ARM64" if is_arm() else "X64" + return f"LLVM-{LLVM_VERSION}-Linux-{arch}.tar.xz" + + if host == "Windows": + arch = "aarch64" if is_arm() else "x86_64" + return f"clang+llvm-{LLVM_VERSION}-{arch}-pc-windows-msvc.tar.xz" + + return None + + +def download(url, dest): + print("downloading " + url) + reported = [0] + + def hook(block, block_size, total): + current = block * block_size + if total > 0 and current - reported[0] >= total / 20: + reported[0] = current + pct = min(100, int(current / total * 100)) + print(f" {pct}% ({current / 1048576:.0f} mb)") + + tmp = dest + ".part" + try: + urllib.request.urlretrieve(url, tmp, hook) + except OSError as error: + if os.path.isfile(tmp): + os.remove(tmp) + raise SystemExit(f"download failed: {error}") + os.replace(tmp, dest) + + +def extract(archive, dest): + print("extracting " + os.path.basename(archive)) + try: + with tarfile.open(archive, "r:xz") as tar: + tar.extractall(dest) + return + except (tarfile.TarError, OSError, EOFError) as error: + # some stripped-down Pythons lack the lzma module; fall back to system tar + print(f" python extraction failed ({error}), trying system tar") + + if os.system(f'tar -xf "{archive}" -C "{dest}"') != 0: + raise SystemExit( + f"could not extract {archive}; unpack it into {VENDORED} by hand" + ) + + +def main(): + if os.path.isdir(os.path.join(VENDORED, "include", "lldb")): + print(f"{VENDORED} already has an llvm with lldb headers") + return 0 + + asset = release_asset() + if asset is None: + raise SystemExit( + f"no pinned llvm release for {platform.system()} " + f"{platform.machine()}; install llvm yourself and set LLVM_PREFIX" + ) + + archive = os.path.join(EXT, asset) + if not os.path.isfile(archive): + url = ( + "https://github.com/llvm/llvm-project/releases/download/" + f"llvmorg-{LLVM_VERSION}/{asset}" + ) + download(url, archive) + + shutil.rmtree(STAGING, ignore_errors=True) + os.makedirs(STAGING) + extract(archive, STAGING) + + unpacked = [ + os.path.join(STAGING, name) + for name in os.listdir(STAGING) + if os.path.isdir(os.path.join(STAGING, name)) + ] + if not unpacked: + raise SystemExit(f"{archive} did not contain an llvm directory") + + shutil.rmtree(VENDORED, ignore_errors=True) + os.rename(unpacked[0], VENDORED) + + shutil.rmtree(STAGING, ignore_errors=True) + os.remove(archive) + + print(f"llvm {LLVM_VERSION} is ready in {VENDORED}") + return 0 + + +if __name__ == "__main__": + sys.exit(main()) |
