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