kit

kit
git clone https://git.ryansepassi.com/git/kit.git
Log | Files | Refs | README

llvm_mingw_sysroot.sh (7852B)


      1 #!/usr/bin/env bash
      2 # Download the pinned llvm-mingw UCRT package into the user cache and extract
      3 # only target headers/libs for kit's Windows cross-compile tests.
      4 
      5 set -eu
      6 
      7 ROOT="$(cd "$(dirname "$0")/.." && pwd)"
      8 RELEASE="${KIT_LLVM_MINGW_RELEASE:-20260602}"
      9 BASE_URL="${KIT_LLVM_MINGW_BASE_URL:-https://github.com/mstorsjo/llvm-mingw/releases/download/$RELEASE}"
     10 
     11 cache_root() {
     12   if [ -n "${KIT_LLVM_MINGW_DOWNLOAD_DIR:-}" ]; then
     13     printf '%s\n' "$KIT_LLVM_MINGW_DOWNLOAD_DIR"
     14     return 0
     15   fi
     16   if [ -n "${XDG_CACHE_HOME:-}" ]; then
     17     printf '%s\n' "$XDG_CACHE_HOME/kit/llvm-mingw/$RELEASE"
     18     return 0
     19   fi
     20   if [ -n "${HOME:-}" ]; then
     21     printf '%s\n' "$HOME/.cache/kit/llvm-mingw/$RELEASE"
     22     return 0
     23   fi
     24   printf 'llvm-mingw-sysroot: set XDG_CACHE_HOME, HOME, or KIT_LLVM_MINGW_DOWNLOAD_DIR\n' >&2
     25   exit 1
     26 }
     27 
     28 DL_ROOT="$(cache_root)"
     29 OUT_ROOT="${KIT_LLVM_MINGW_ROOT:-$ROOT/build/llvm-mingw/$RELEASE/ucrt}"
     30 
     31 usage() {
     32   cat <<EOF
     33 usage: scripts/llvm_mingw_sysroot.sh <command> [arch]
     34 
     35 commands:
     36   doctor              print selected package and tool availability
     37   fetch               download and verify the host llvm-mingw UCRT package
     38   prepare [arch|all]  extract target include/ and lib/ dirs (default: all)
     39   path <arch>         print the extracted target sysroot path
     40   env <arch>          print a KIT_SYSROOT export for the target sysroot
     41 
     42 arches:
     43   x64 | x86_64 | amd64 | aarch64 | arm64 | aa64 | all
     44 
     45 downloads:
     46   $DL_ROOT
     47 
     48 extracted sysroots:
     49   $OUT_ROOT
     50 EOF
     51 }
     52 
     53 die() {
     54   printf 'llvm-mingw-sysroot: %s\n' "$*" >&2
     55   exit 1
     56 }
     57 
     58 canon_arch() {
     59   case "${1:-all}" in
     60     x64|x86_64|amd64) echo x64 ;;
     61     aarch64|arm64|aa64) echo aarch64 ;;
     62     all|"") echo all ;;
     63     *) die "unknown arch '${1:-}'" ;;
     64   esac
     65 }
     66 
     67 target_triple() {
     68   case "$(canon_arch "$1")" in
     69     x64) echo x86_64-w64-mingw32 ;;
     70     aarch64) echo aarch64-w64-mingw32 ;;
     71     *) die "target_triple requires a concrete arch" ;;
     72   esac
     73 }
     74 
     75 host_package() {
     76   local os mach
     77   os="$(uname -s 2>/dev/null || echo unknown)"
     78   mach="$(uname -m 2>/dev/null || echo unknown)"
     79   case "$os" in
     80     Darwin)
     81       echo "llvm-mingw-$RELEASE-ucrt-macos-universal.tar.xz|d3310f9b86b368900850af8bc95da20648f9fc6b0be3bb64dbf8fb18d7c0894f|tar"
     82       ;;
     83     Linux)
     84       case "$mach" in
     85         x86_64|amd64)
     86           echo "llvm-mingw-$RELEASE-ucrt-ubuntu-22.04-x86_64.tar.xz|9d191203f9768ead60662d3ae53cdf28e0a28b1e6d44b7f329b9202cb2add337|tar"
     87           ;;
     88         aarch64|arm64)
     89           echo "llvm-mingw-$RELEASE-ucrt-ubuntu-22.04-aarch64.tar.xz|e71b61c968f65f94ed3878ca22ab663d7854d91c053c1b8a824ac2f1c9a18503|tar"
     90           ;;
     91         *)
     92           die "unsupported Linux host architecture: $mach"
     93           ;;
     94       esac
     95       ;;
     96     MINGW*|MSYS*|CYGWIN*)
     97       case "$mach" in
     98         x86_64|amd64)
     99           echo "llvm-mingw-$RELEASE-ucrt-x86_64.zip|3de3eda9377bbaf35f8c9001f190380f63b8ee981fa55d3ae9d7cce7c6ad7c70|zip"
    100           ;;
    101         aarch64|arm64)
    102           echo "llvm-mingw-$RELEASE-ucrt-aarch64.zip|cb5c20fbe1808e31ada5cbe4efd9daa2fee19c91dac6ec5ca1ac46a9c7247e37|zip"
    103           ;;
    104         *)
    105           die "unsupported Windows host architecture: $mach"
    106           ;;
    107       esac
    108       ;;
    109     *)
    110       die "unsupported host OS: $os"
    111       ;;
    112   esac
    113 }
    114 
    115 pkg_field() {
    116   local n=$1 pkg=$2
    117   printf '%s\n' "$pkg" | awk -F'|' -v n="$n" '{ print $n }'
    118 }
    119 
    120 sha256_file() {
    121   if command -v shasum >/dev/null 2>&1; then
    122     shasum -a 256 "$1" | awk '{ print $1 }'
    123     return 0
    124   fi
    125   if command -v sha256sum >/dev/null 2>&1; then
    126     sha256sum "$1" | awk '{ print $1 }'
    127     return 0
    128   fi
    129   die "missing shasum or sha256sum"
    130 }
    131 
    132 verify_archive() {
    133   local path=$1 expect=$2 got
    134   got="$(sha256_file "$path")"
    135   [ "$got" = "$expect" ] ||
    136     die "checksum mismatch for $(basename "$path"): got $got want $expect"
    137 }
    138 
    139 archive_path() {
    140   local pkg name
    141   pkg="$(host_package)"
    142   name="$(pkg_field 1 "$pkg")"
    143   printf '%s\n' "$DL_ROOT/$name"
    144 }
    145 
    146 fetch_package() {
    147   local pkg name digest url path
    148   pkg="$(host_package)"
    149   name="$(pkg_field 1 "$pkg")"
    150   digest="$(pkg_field 2 "$pkg")"
    151   url="$BASE_URL/$name"
    152   path="$DL_ROOT/$name"
    153   mkdir -p "$DL_ROOT"
    154   if [ -f "$path" ]; then
    155     verify_archive "$path" "$digest"
    156     printf 'archive already verified: %s\n' "$path"
    157     return 0
    158   fi
    159   command -v curl >/dev/null 2>&1 || die "curl not found"
    160   printf 'download: %s\n' "$url"
    161   curl -fL --retry 3 --retry-delay 2 --continue-at - -o "$path.part" "$url"
    162   mv "$path.part" "$path"
    163   verify_archive "$path" "$digest"
    164   printf 'verified: %s\n' "$path"
    165 }
    166 
    167 archive_top() {
    168   local path=$1 kind=$2
    169   case "$kind" in
    170     tar) tar -tf "$path" | sed -n '1s#/.*##p' ;;
    171     zip) unzip -Z1 "$path" | sed -n '1s#/.*##p' ;;
    172   esac
    173 }
    174 
    175 extract_arch() {
    176   local arch triple pkg kind path top tmp out
    177   arch="$(canon_arch "$1")"
    178   [ "$arch" != all ] || die "extract_arch requires a concrete arch"
    179   triple="$(target_triple "$arch")"
    180   pkg="$(host_package)"
    181   kind="$(pkg_field 3 "$pkg")"
    182   path="$(archive_path)"
    183   fetch_package
    184   top="$(archive_top "$path" "$kind")"
    185   [ -n "$top" ] || die "could not determine archive top directory"
    186   tmp="$OUT_ROOT/.extract-$triple"
    187   out="$OUT_ROOT/$triple"
    188   rm -rf "$tmp" "$out.tmp"
    189   mkdir -p "$tmp" "$OUT_ROOT"
    190   case "$kind" in
    191     tar)
    192       tar -xf "$path" -C "$tmp" \
    193         "$top/$triple/include" \
    194         "$top/$triple/lib" \
    195         "$top/generic-w64-mingw32/include"
    196       ;;
    197     zip)
    198       command -v unzip >/dev/null 2>&1 || die "unzip not found"
    199       unzip -q "$path" \
    200         "$top/$triple/include*" \
    201         "$top/$triple/lib/*" \
    202         "$top/generic-w64-mingw32/include/*" \
    203         -d "$tmp"
    204       ;;
    205   esac
    206   [ -r "$tmp/$top/$triple/include/windows.h" ] ||
    207     die "archive did not contain readable $triple/include/windows.h"
    208   [ -d "$tmp/$top/$triple/lib" ] ||
    209     die "archive did not contain $triple/lib"
    210   if [ -d "$tmp/$top/generic-w64-mingw32" ]; then
    211     rm -rf "$OUT_ROOT/generic-w64-mingw32.tmp"
    212     mv "$tmp/$top/generic-w64-mingw32" "$OUT_ROOT/generic-w64-mingw32.tmp"
    213     rm -rf "$OUT_ROOT/generic-w64-mingw32"
    214     mv "$OUT_ROOT/generic-w64-mingw32.tmp" "$OUT_ROOT/generic-w64-mingw32"
    215   fi
    216   mv "$tmp/$top/$triple" "$out.tmp"
    217   rm -rf "$out"
    218   mv "$out.tmp" "$out"
    219   rm -rf "$tmp"
    220   {
    221     printf 'release=%s\n' "$RELEASE"
    222     printf 'asset=%s\n' "$(basename "$path")"
    223     printf 'url=%s/%s\n' "$BASE_URL" "$(basename "$path")"
    224     printf 'sha256=%s\n' "$(pkg_field 2 "$pkg")"
    225     printf 'target=%s\n' "$triple"
    226   } > "$out/PROVENANCE"
    227   printf 'sysroot ready: %s\n' "$out"
    228 }
    229 
    230 prepare() {
    231   local arch
    232   arch="$(canon_arch "${1:-all}")"
    233   if [ "$arch" = all ]; then
    234     extract_arch x64
    235     extract_arch aarch64
    236   else
    237     extract_arch "$arch"
    238   fi
    239 }
    240 
    241 sysroot_path() {
    242   local arch triple
    243   arch="$(canon_arch "$1")"
    244   [ "$arch" != all ] || die "path requires a concrete arch"
    245   triple="$(target_triple "$arch")"
    246   printf '%s\n' "$OUT_ROOT/$triple"
    247 }
    248 
    249 doctor() {
    250   local pkg
    251   pkg="$(host_package)"
    252   printf 'host: %s/%s\n' "$(uname -s 2>/dev/null)" "$(uname -m 2>/dev/null)"
    253   printf 'release: %s\n' "$RELEASE"
    254   printf 'asset: %s\n' "$(pkg_field 1 "$pkg")"
    255   printf 'download cache: %s\n' "$DL_ROOT"
    256   printf 'extract root: %s\n' "$OUT_ROOT"
    257   for tool in curl tar shasum sha256sum unzip; do
    258     if command -v "$tool" >/dev/null 2>&1; then
    259       printf '  OK      %s (%s)\n' "$tool" "$(command -v "$tool")"
    260     else
    261       printf '  MISSING %s\n' "$tool"
    262     fi
    263   done
    264   for arch in x64 aarch64; do
    265     printf '  %-7s %s\n' "$arch" "$(sysroot_path "$arch")"
    266   done
    267 }
    268 
    269 cmd="${1:-}"
    270 case "$cmd" in
    271   doctor) doctor ;;
    272   fetch) fetch_package ;;
    273   prepare) shift; prepare "${1:-all}" ;;
    274   path) [ $# -eq 2 ] || { usage; exit 2; }; sysroot_path "$2" ;;
    275   env)
    276     [ $# -eq 2 ] || { usage; exit 2; }
    277     printf 'export KIT_SYSROOT=%s\n' "$(sysroot_path "$2")"
    278     ;;
    279   -h|--help|help|"") usage ;;
    280   *) usage; exit 2 ;;
    281 esac