Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
190 changes: 190 additions & 0 deletions projects/llvm.org/mingw-w64/package.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,190 @@
# llvm-mingw: LLVM-based mingw-w64 toolchain.
# Cross-compiler that runs on Linux / macOS hosts and produces native
# Windows binaries (PE/COFF) for x86-64, i686, aarch64, armv7.
#
# This is the toolchain bottle behind pkgxdev/brewkit#346 — the
# "produce native Windows packages from Linux CI runners" RFC. Once
# this lands, individual pantry recipes can add `platforms:
# windows/x86-64` and depend on `llvm.org/mingw-w64` to cross-compile.
#
# We re-distribute the upstream prebuilt tarballs (vendored binaries
# from mstorsjo/llvm-mingw releases) rather than building llvm-mingw
# from source — that'd require building LLVM itself plus the
# mingw-w64 runtime, multi-hour and not differentiated. Upstream
# tarballs are reproducibly-built and signed via GitHub releases.

# Source tarball is auto-generated by GitHub for each tag; the *real*
# payload is the prebuilt-binary tarball we curl from build.script
# (same `warnings: vendored` pattern as ziglang.org).
distributable:
~
# url: https://github.com/mstorsjo/llvm-mingw/archive/refs/tags/{{ version.raw }}.tar.gz
# strip-components: 1

versions:
github: mstorsjo/llvm-mingw

# llvm-mingw's host-platform tarballs cover Linux x86-64, Linux aarch64,
# and macOS universal (x86-64 + aarch64). No Windows-host variant for
# our purposes (we'd rather have Windows binaries be a *target*, not
# a host).
#
# Hosts: linux + darwin. (Earlier rounds restricted to linux because
# darwin failed and logs weren't externally accessible; @jhheider
# shared the log on pkgxdev/pantry#12984 — the failure was the test
# step invoking the compiler by bare name, which brewkit's sandbox
# auto-fetched as a different clang. Fix below: invoke by full path.)
platforms:
- linux
- darwin

warnings:
- vendored # we redistribute upstream prebuilt binaries

build:
dependencies:
curl.se: "*"
gnu.org/tar: "*"
tukaani.org/xz: "*"

env:
linux/x86-64:
PLATFORM: ubuntu-22.04-x86_64
linux/aarch64:
PLATFORM: ubuntu-22.04-aarch64
darwin/x86-64:
PLATFORM: macos-universal
darwin/aarch64:
PLATFORM: macos-universal
script:
# Map our host triple → upstream's tarball naming convention,
# then download + extract the prebuilt binary toolchain.
- URL="https://github.com/mstorsjo/llvm-mingw/releases/download/{{version.raw}}/llvm-mingw-{{version.raw}}-ucrt-${PLATFORM}.tar.xz"
- echo "fetching $URL"
- curl -Lfo llvm-mingw.tar.xz "$URL"
- tar Jxf llvm-mingw.tar.xz --strip-components=1 -C .

# Copy the prebuilt toolchain into {{prefix}}. Upstream's drivers
# (x86_64-w64-mingw32-clang etc.) are wrappers that call into
# ../lib/clang/.../bin via relative paths — already relocatable.
# brewkit doesn't pre-create {{prefix}}, so mkdir it first;
# otherwise `cp -a bin {{prefix}}/` fails with "cannot create
# directory" on the first cp.
- mkdir -p "{{prefix}}"
- cp -a bin "{{prefix}}/"
- cp -a lib "{{prefix}}/"
- |
for d in share include; do
[ -d "$d" ] && cp -a "$d" "{{prefix}}/"
done

test:
# winehq.org/wine is a soft dep — if present, we actually run the
# cross-compiled .exe through wine and verify the output. If not,
# we fall back to a PE magic-byte check. See pkgxdev/brewkit#346
# discussion: wine in pantry would let us validate the cross-compile
# chain end-to-end without GitHub Windows runners.
dependencies:
winehq.org: "*"
env:
WINEDEBUG: -all
WINEDLLOVERRIDES: "mscoree=;mshtml="
WINEPREFIX: $PWD/.wine
# Pin our own bottle's binaries by full path. brewkit's test
# sandbox treats unfamiliar commands as external deps and routes
# them through `pkgx auto-fetch`, which (on darwin in earlier
# rounds) picked up a different clang that didn't know our mingw
# headers. Full path bypasses that.
CLANG_X86_64: "{{prefix}}/bin/x86_64-w64-mingw32-clang"
CLANG_AARCH64: "{{prefix}}/bin/aarch64-w64-mingw32-clang"
script:
# Diagnostics first — surface env + filesystem state so the
# darwin self-hosted-runner failure (logs not externally
# accessible) becomes visible to maintainers.
- |
echo "── env diagnostics ──"
echo "CLANG_X86_64=$CLANG_X86_64"
echo "CLANG_AARCH64=$CLANG_AARCH64"
echo "── filesystem check ──"
ls -la "$CLANG_X86_64" 2>&1 || echo "(missing: $CLANG_X86_64)"
ls -la "$CLANG_AARCH64" 2>&1 || echo "(missing: $CLANG_AARCH64)"

# Pre-flight: can clang actually run on this host?
# On a buster-sandbox host (glibc 2.28) clang can't load —
# `GLIBC_2.34 not found`. Skip gracefully then.
- |
if ! "$CLANG_X86_64" --version 2>&1; then
echo "clang can't run on this host (likely glibc < 2.34) —"
echo "skipping cross-compile test, recipe install OK."
exit 0
fi

# Cross-compile a trivial Windows binary for x86-64 and aarch64.
- run: cp $FIXTURE hello.c
fixture: |
#include <stdio.h>
int main(void) {
printf("Hello from native Windows cross-compile.\n");
return 0;
}
- $CLANG_X86_64 -o hello-x86_64.exe hello.c
- $CLANG_AARCH64 -o hello-aarch64.exe hello.c

# Static signature check: PE32+ starts with "MZ" at offset 0.
# head -c 2 reads the raw bytes; "MZ" are printable so the shell
# capture works without any od/tr/sed gymnastics (which had subtle
# BSD-vs-GNU output-format differences and broke on darwin).
- |
for f in hello-x86_64.exe hello-aarch64.exe; do
case "$(head -c 2 "$f")" in
MZ) echo "$f: PE/COFF DOS header OK" ;;
*) echo "$f: NOT a PE binary"; exit 1 ;;
esac
done

# Dynamic check: actually run the .exe through wine. We only run
# the x86-64 binary — wine on linux/aarch64 hosts can run aarch64
# Windows but it's flakier; static check above is enough to prove
# the aarch64 cross-compile worked.
#
# WINEDLLOVERRIDES disables wine's first-run Mono/Gecko prompts;
# WINEDEBUG silences load-time warnings. Both standard for headless.
- |
if command -v wine64 >/dev/null 2>&1; then
WINE=wine64
elif command -v wine >/dev/null 2>&1; then
WINE=wine
else
echo "wine not available — skipping runtime test (compile + PE-magic-check only)"
exit 0
fi

- echo "running hello-x86_64.exe under $($WINE --version)"
- out=$($WINE hello-x86_64.exe)
- 'echo "wine stdout: $out"'
- |
case "$out" in
"Hello from native Windows cross-compile.") echo "RUN PASS" ;;
*) echo "RUN FAIL: unexpected output"; exit 1 ;;
esac

provides:
# x86_64 cross drivers
- bin/x86_64-w64-mingw32-clang
- bin/x86_64-w64-mingw32-clang++
- bin/x86_64-w64-mingw32-gcc
- bin/x86_64-w64-mingw32-g++
# aarch64 cross drivers
- bin/aarch64-w64-mingw32-clang
- bin/aarch64-w64-mingw32-clang++
- bin/aarch64-w64-mingw32-gcc
- bin/aarch64-w64-mingw32-g++
# i686 cross drivers
- bin/i686-w64-mingw32-clang
- bin/i686-w64-mingw32-clang++
# PE-aware tooling (analog of binutils for ELF). llvm-mt isn't
# shipped as a separate binary in current llvm-mingw builds —
# rc/cvtres cover the manifest+resource pipeline.
- bin/llvm-rc # resource compiler (rc.exe)
- bin/llvm-cvtres # COFF tooling
- bin/lld-link # MSVC-compat linker (link.exe)
Loading