windows_cross.sh (3622B)
1 #!/usr/bin/env bash 2 # Cross-compile the kit binary itself into a Windows PE/COFF kit.exe, using the 3 # host build/kit as the cross-compiler against the llvm-mingw UCRT sysroot. 4 # 5 # Unlike the Linux/FreeBSD bootstraps (native 3-stage builds inside a VM/ 6 # container), the Windows kit binary is produced by CROSS-compiling on the dev 7 # host: there is no C compiler in the Windows VM to seed a native build, but the 8 # already-built build/kit can compile + link every libkit/driver TU for the 9 # Windows target. The build system selects driver/env/windows.c by overriding 10 # HOST_OS=windows (mk/env.mk normally derives it from `uname`). 11 # 12 # usage: scripts/windows_cross.sh [arch] 13 # arch aarch64 (default) | x64 14 # 15 # env: 16 # KIT_WIN_OPT codegen opt level (default -O0; -O1 exercises the optimizer) 17 # 18 # Output: build/win-cross/<arch>/kit.exe (a PE32+ console executable). 19 # 20 # Prerequisites: 21 # make bin # the host build/kit cross-compiler 22 # scripts/llvm_mingw_sysroot.sh prepare <arch> # mingw UCRT headers + libs 23 # make rt-aarch64-windows | rt-x86_64-pc-windows # target runtime (if linking rt) 24 25 set -eu 26 27 ROOT="$(cd "$(dirname "$0")/.." && pwd)" 28 cd "$ROOT" 29 30 ARCH="${1:-aarch64}" 31 case "$ARCH" in 32 aarch64|arm64|aa64) ARCH=aarch64; TRIPLE=aarch64-windows; HOST_ARCH=aarch64 ;; 33 x64|x86_64|amd64) ARCH=x64; TRIPLE=x86_64-windows; HOST_ARCH=x86_64 ;; 34 *) echo "windows_cross: unsupported arch '$ARCH' (want aarch64|x64)" >&2; exit 2 ;; 35 esac 36 37 KIT="$ROOT/build/kit" 38 [ -x "$KIT" ] || { echo "windows_cross: $KIT missing; run 'make bin' first" >&2; exit 1; } 39 40 SR="$("$ROOT/scripts/llvm_mingw_sysroot.sh" path "$ARCH" 2>/dev/null || true)" 41 [ -n "$SR" ] && [ -r "$SR/include/windows.h" ] || { 42 echo "windows_cross: mingw sysroot for $ARCH missing; run" >&2 43 echo " scripts/llvm_mingw_sysroot.sh prepare $ARCH" >&2 44 exit 1 45 } 46 47 BUILD_DIR="build/win-cross/$ARCH" 48 TC="$ROOT/$BUILD_DIR/toolchain" 49 mkdir -p "$TC" 50 51 # A single-word cc wrapper that injects -target/--sysroot: make splits a 52 # multi-word `CC=...` command-line value on whitespace, so the flags can't ride 53 # on CC directly. The ar/ranlib/as/ld busybox links dispatch by argv[0] basename 54 # (same pattern as mk/bootstrap.mk's stage symlinks). 55 cat > "$TC/cc" <<EOF 56 #!/bin/sh 57 exec "$KIT" cc -target $TRIPLE --sysroot "$SR" "\$@" 58 EOF 59 chmod +x "$TC/cc" 60 for t in ar ranlib as ld; do ln -sf "$KIT" "$TC/$t"; done 61 62 # kit cc emits no -MMD dependency files, so make cannot see header edits or a 63 # rebuilt compiler. Wipe the object tree (keeping the toolchain) so every run is 64 # a correct full rebuild by the current build/kit. 65 find "$BUILD_DIR" -mindepth 1 -maxdepth 1 ! -name toolchain -exec rm -rf {} + 66 67 # RELEASE=1 supplies -ffunction-sections -fdata-sections internally (no 68 # multi-word CLI value, which make would mis-split); --gc-sections then drops 69 # the dead per-function/data sections the mingw headers' unused static inlines 70 # pull in. HOST_OPTFLAGS keeps the simpler -O0 codegen and HOST_MODE_CPPFLAGS= 71 # keeps asserts enabled; HOST_SYSROOT_*FLAGS are cleared because the sysroot 72 # rides on the cc wrapper's --sysroot, not env.mk's Darwin -isysroot. 73 JOBS="$(getconf _NPROCESSORS_ONLN 2>/dev/null || echo 4)" 74 make bin -j"$JOBS" \ 75 BUILD_DIR="$BUILD_DIR" \ 76 HOST_OS=windows HOST_ARCH="$HOST_ARCH" \ 77 RELEASE=1 HOST_OPTFLAGS="${KIT_WIN_OPT:--O0}" HOST_MODE_CPPFLAGS= \ 78 HOST_MODE_LDFLAGS=-Wl,--gc-sections \ 79 HOST_SYSROOT_CFLAGS= HOST_SYSROOT_LDFLAGS= \ 80 CC="$TC/cc" AR="$TC/ar" 81 82 cp "$BUILD_DIR/kit" "$BUILD_DIR/kit.exe" 83 printf 'windows_cross: built %s\n' "$BUILD_DIR/kit.exe" 84 file "$BUILD_DIR/kit.exe" 2>/dev/null || true