github: Add an optional set of smoke tests for github actions

This adds an optional github actions workflow, with a number of
smoke test verifications of mingw-w64:
- With an existing release of llvm-mingw, rebuild all the runtimes
 - This done for the CRT configurations ucrtbase, ucrt and msvcrt
- Run the llvm-mingw smoke tests on Windows (testing compilation
  for all 4 architectures, testing running on x86)
- Run the libcxx testsuite on Windows (i686 and x86_64)
- Test cross-building ffmpeg for all 4 architectures
- Test building and running ffmpeg with its testsuite on Windows
  (i686 and x86_64)
- Test building a GCC cross compiler from scratch
- Test cross-building a Windows hosted GCC using the GCC above
- Run a small set of basic tests with the GCC toolchain

This allows doing some amount of automatic testing of mingw-w64,
covering most common build configurations, avoiding regressing
any of these cases.

While mingw-w64 isn't primarily hosted on github, this wouldn't
be a mandatory/integrated testsuite per se. But many mingw-w64
developers do use github and can benefit from this test setup,
and by having it in-repo, it's easier to coordinate updates to
the test configuration when that is needed. It also makes it
easier for others to contribute more testing configurations.

Signed-off-by: Martin Storsjö <martin@martin.st>
diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
new file mode 100644
index 0000000..37daa7d
--- /dev/null
+++ b/.github/workflows/build.yml
@@ -0,0 +1,539 @@
+name: Test mingw-w64
+on:
+  push:
+
+jobs:
+  llvm-mingw:
+    runs-on: ubuntu-latest
+    strategy:
+      fail-fast: false
+      matrix:
+        crt:
+          - ucrt
+          - ucrtbase
+          - msvcrt
+    steps:
+      - name: Check out llvm-mingw build scripts
+        uses: actions/checkout@v4
+        with:
+          repository: mstorsjo/llvm-mingw
+          ref: 20250402
+      - name: Check out the mingw-w64 version to be tested
+        uses: actions/checkout@v4
+        with:
+          path: mingw-w64
+      - name: Regenerate mingw-w64 files
+        run: |
+          sudo apt-get update && sudo apt-get install autoconf automake
+          cd mingw-w64/mingw-w64-headers
+          autoreconf
+          cd ../mingw-w64-crt
+          autoreconf
+          cd ../mingw-w64-libraries/winpthreads
+          autoreconf
+          cd ../winstorecompat
+          autoreconf
+      - name: Rebuild the runtimes
+        run: |
+          sudo apt-get update && sudo apt-get install ninja-build
+          DISTRO=ubuntu-20.04-x86_64
+          src_crt=${{matrix.crt}}
+          if [ "$src_crt" = "ucrtbase" ]; then
+              src_crt=ucrt
+          fi
+          curl -LO https://github.com/mstorsjo/llvm-mingw/releases/download/20250402/llvm-mingw-20250402-$src_crt-$DISTRO.tar.xz
+          tar -Jxf llvm-mingw-*.tar.xz
+          rm llvm-mingw-*.tar.xz
+          mkdir install
+          mv llvm-mingw-*-ubuntu-* install/llvm-mingw
+          ./build-all.sh $(pwd)/install/llvm-mingw --no-tools --wipe-runtimes --with-default-msvcrt=${{matrix.crt}}
+          ./test-libcxx-module.sh $(pwd)/install/llvm-mingw
+          # Run basic smoke tests on the reassembled toolchain
+          RUN_I686=false RUN_X86_64=false ./run-tests.sh $(pwd)/install/llvm-mingw
+          cd install
+          TAG=testing
+          NAME=llvm-mingw-$TAG-${{matrix.crt}}-$DISTRO
+          mv llvm-mingw $NAME
+          tar -Jcf ../$NAME.tar.xz --format=ustar --numeric-owner --owner=0 --group=0 --sort=name $NAME
+          mv $NAME llvm-mingw
+      - uses: actions/upload-artifact@v4
+        with:
+          name: linux-${{matrix.crt}}-x86_64-toolchain
+          path: |
+            llvm-mingw-*.tar.xz
+          retention-days: 7
+      - name: Update runtimes in Windows toolchains
+        run: |
+          rm llvm-mingw-*.tar.xz
+          mkdir cross
+          cd cross
+
+          for arch in i686 x86_64; do
+            src_crt=${{matrix.crt}}
+            if [ "$src_crt" = "ucrtbase" ]; then
+                src_crt=ucrt
+            fi
+            curl -LO https://github.com/mstorsjo/llvm-mingw/releases/download/20250402/llvm-mingw-20250402-$src_crt-$arch.zip
+            unzip -q llvm-mingw-*.zip
+            rm llvm-mingw-*.zip
+            mv llvm-mingw-* llvm-mingw
+            rm -rf llvm-mingw/*-w64-mingw32 llvm-mingw/include
+            ../prepare-cross-toolchain.sh ../install/llvm-mingw llvm-mingw $arch
+            TAG=testing
+            NAME=llvm-mingw-$TAG-${{matrix.crt}}-$arch
+            mv llvm-mingw $NAME
+            zip -9rq ../$NAME.zip $NAME
+            rm -rf $NAME
+          done
+      - uses: actions/upload-artifact@v4
+        with:
+          name: windows-${{matrix.crt}}-i686-toolchain
+          path: |
+            llvm-mingw-*-i686.zip
+          retention-days: 7
+      - uses: actions/upload-artifact@v4
+        with:
+          name: windows-${{matrix.crt}}-x86_64-toolchain
+          path: |
+            llvm-mingw-*-x86_64.zip
+          retention-days: 7
+
+  test-llvm-mingw:
+    needs: [llvm-mingw]
+    runs-on: windows-latest
+    defaults:
+      run:
+        shell: msys2 {0}
+    strategy:
+      fail-fast: false
+      matrix:
+        arch:
+          - x86_64
+          - i686
+        crt:
+          - ucrt
+          - ucrtbase
+          - msvcrt
+    steps:
+      - uses: msys2/setup-msys2@v2
+        with:
+          msystem: mingw64
+          install: >-
+            unzip
+            make
+      - uses: actions/download-artifact@v4
+        with:
+          name: windows-${{matrix.crt}}-${{matrix.arch}}-toolchain
+      - name: Unpack toolchain
+        run: |
+          unzip -q llvm-mingw-*.zip
+          rm llvm-mingw-*.zip
+          mv llvm-mingw-* /llvm-mingw
+          echo /llvm-mingw/bin >> $GITHUB_PATH
+      - name: Check out llvm-mingw tests
+        uses: actions/checkout@v4
+        with:
+          repository: mstorsjo/llvm-mingw
+          ref: 20250402
+      - name: Run tests
+        run: |
+          ./run-tests.sh /llvm-mingw
+      - name: Run extra tests with crt-test
+        run: |
+          export PATH=/llvm-mingw/bin:$PATH
+          for arch in i686 x86_64 armv7 aarch64; do
+            for crt in msvcrt-ansi msvcrt-noansi ucrt ucrtbase; do
+              case $crt in
+              msvcrt*) defs="-D__MSVCRT_VERSION__=0x700"; lib=msvcrt-os ;;
+              ucrt*) defs="-D_UCRT"; lib=$crt ;;
+              esac
+              case $crt in
+              *-noansi) defs="$defs -D__USE_MINGW_ANSI_STDIO=0" ;;
+              *-ansi) defs="$defs -D__USE_MINGW_ANSI_STDIO=1" ;;
+              esac
+              name=crt-test-$arch-$crt
+              $arch-w64-mingw32-clang $defs -fno-builtin test/crt-test.c -o $name-regular.exe -lmingwex -l$lib -O2
+              $arch-w64-mingw32-clang $defs -fno-builtin test/crt-test.c -o $name-crt-first.exe -l$lib -O2
+              echo $name
+              case $arch in
+              *86*) ./$name-regular.exe ; ./$name-crt-first.exe ;;
+              esac
+            done
+          done
+
+  test-libcxx:
+    needs: [llvm-mingw]
+    runs-on: windows-latest
+    strategy:
+      fail-fast: false
+      matrix:
+        include:
+          - { arch: x86_64, prefix: i686-w64-mingw32- }
+          - { arch: x86_64, prefix: }
+    steps:
+      - name: Install dependencies
+        run: |
+          choco install ninja
+      - uses: actions/download-artifact@v4
+        with:
+          name: windows-ucrt-${{matrix.arch}}-toolchain
+      - name: Unpack toolchain
+        run: |
+          Expand-Archive llvm-mingw-*.zip -DestinationPath .
+          del llvm-mingw-*.zip
+          mv llvm-mingw-* c:\llvm-mingw
+          echo "c:\llvm-mingw\bin" | Out-File -FilePath $Env:GITHUB_PATH -Encoding utf8 -Append
+          echo "c:\llvm-mingw\python\bin" | Out-File -FilePath $Env:GITHUB_PATH -Encoding utf8 -Append
+          echo "PYTHON_EXE=c:/llvm-mingw/python/bin/python3.exe" | Out-File -FilePath $Env:GITHUB_ENV -Encoding utf8 -Append
+      - name: Check out llvm-mingw scripts
+        uses: actions/checkout@v4
+        with:
+          repository: mstorsjo/llvm-mingw
+          ref: 20250402
+      - name: Checkout llvm-project
+        run: |
+          bash -c "CHECKOUT_ONLY=1 ./build-llvm.sh"
+      - name: Build and test libcxx
+        run: |
+          cd llvm-project
+          mkdir build
+          cd build
+          cmake ../runtimes `
+            -G Ninja `
+            -DCMAKE_BUILD_TYPE=Release `
+            -DPython3_EXECUTABLE="$Env:PYTHON_EXE" `
+            -DLIBCXX_ENABLE_WERROR=YES `
+            -DLLVM_ENABLE_RUNTIMES="libcxx;libcxxabi;libunwind" `
+            -DLIBCXX_CXX_ABI=libcxxabi `
+            -DCMAKE_C_COMPILER=${{matrix.prefix}}clang `
+            -DCMAKE_CXX_COMPILER=${{matrix.prefix}}clang++ `
+            -DLIBCXXABI_ENABLE_SHARED=NO `
+            -DLIBCXX_ENABLE_STATIC_ABI_LIBRARY=YES `
+            -DLIBCXX_USE_COMPILER_RT=YES `
+            -DLIBCXXABI_USE_COMPILER_RT=YES `
+            -DLIBUNWIND_USE_COMPILER_RT=YES `
+            -DLIBCXXABI_USE_LLVM_UNWINDER=YES `
+            -DLIBCXX_EXTRA_SITE_DEFINES="__USE_MINGW_ANSI_STDIO=1" `
+            -DLLVM_LIT_ARGS="-v --time-tests"
+          ninja
+          ninja check-cxx check-cxxabi check-unwind
+
+  linux-test-cross-build-ffmpeg:
+    needs: [llvm-mingw]
+    runs-on: ubuntu-latest
+    strategy:
+      fail-fast: false
+      matrix:
+        arch:
+          - i686
+          - x86_64
+          - armv7
+          - aarch64
+    steps:
+      - uses: actions/download-artifact@v4
+        with:
+          name: linux-ucrt-x86_64-toolchain
+      - name: Unpack cross toolchain
+        run: |
+          tar -Jxf llvm-mingw-*.tar.xz
+          rm llvm-mingw-*.tar.xz
+          sudo mv llvm-mingw* /opt/llvm-mingw
+          echo /opt/llvm-mingw/bin >> $GITHUB_PATH
+      - name: Checkout ffmpeg
+        uses: actions/checkout@v4
+        with:
+          repository: ffmpeg/ffmpeg
+          ref: n6.1.2
+          path: ffmpeg
+      - name: Build ffmpeg
+        run: |
+          sudo apt-get update && sudo apt-get install nasm
+          mkdir ffmpeg-build
+          cd ffmpeg-build
+          ../ffmpeg/configure --arch=${{matrix.arch}} --target-os=mingw32 --cross-prefix=${{matrix.arch}}-w64-mingw32- --enable-gpl
+          make -j$(nproc)
+
+  test-ffmpeg:
+    needs: [llvm-mingw]
+    runs-on: windows-latest
+    strategy:
+      fail-fast: false
+      matrix:
+        arch:
+          - i686
+          - x86_64
+    defaults:
+      run:
+        shell: msys2 {0}
+    steps:
+      - name: Avoid git checking out files with CRLF
+        shell: cmd
+        run: |
+          git config --global core.autocrlf false
+      - uses: msys2/setup-msys2@v2
+        with:
+          msystem: mingw64
+          install: >-
+            unzip
+            make
+            rsync
+            diffutils
+          pacboy: >-
+            nasm:p
+      - uses: actions/download-artifact@v4
+        with:
+          name: windows-ucrt-${{matrix.arch}}-toolchain
+      - name: Unpack toolchain
+        run: |
+          unzip -q llvm-mingw-*.zip
+          rm llvm-mingw-*.zip
+          mv llvm-mingw-* /llvm-mingw
+          echo /llvm-mingw/bin >> $GITHUB_PATH
+      - name: Checkout ffmpeg
+        uses: actions/checkout@v4
+        with:
+          repository: ffmpeg/ffmpeg
+          ref: n6.1.2
+          path: ffmpeg
+      - name: Cache FATE samples
+        uses: actions/cache@v4
+        with:
+          path: fate-samples
+          key: fate-samples
+      - name: Build & test ffmpeg
+        run: |
+          export PATH=/llvm-mingw/bin:$PATH
+          mkdir ffmpeg-build
+          cd ffmpeg-build
+          ../ffmpeg/configure --samples=../fate-samples --enable-gpl
+          make -j$(nproc)
+          make fate-rsync
+          make -j$(nproc) fate
+
+  gcc:
+    runs-on: ubuntu-latest
+    strategy:
+      fail-fast: false
+      matrix:
+        crt:
+          - ucrt
+          - msvcrt
+        arch:
+          - i686
+          - x86_64
+    steps:
+      - name: Download dependencies
+        run: |
+          sudo apt-get update && sudo apt-get install libgmp-dev libmpfr-dev libmpc-dev autoconf automake
+      - name: Build binutils
+        run: |
+          curl -LO https://ftp.gnu.org/gnu/binutils/binutils-2.42.tar.xz
+          tar -Jxf binutils-*.tar.xz
+          rm binutils-*.tar.xz
+          cd binutils-*
+          mkdir build
+          cd build
+          ../configure --prefix=$(pwd)/../../prefix --target=${{matrix.arch}}-w64-mingw32 --disable-werror --disable-multilib
+          make -j$(nproc)
+          make install-strip
+          echo $(pwd)/../../prefix/bin >> $GITHUB_PATH
+      - name: Build the base GCC
+        run: |
+          curl -LO https://ftp.gnu.org/gnu/gcc/gcc-14.1.0/gcc-14.1.0.tar.xz
+          tar -Jxf gcc-*.tar.xz
+          rm gcc-*.tar.xz
+          cd gcc-*
+          mkdir build
+          cd build
+          ../configure --prefix=$(pwd)/../../prefix --target=${{matrix.arch}}-w64-mingw32 --enable-languages=c,c++ --disable-multilib --enable-threads=posix
+          make -j$(nproc) all-gcc
+          make install-strip-gcc
+      - name: Check out the mingw-w64 version to be tested
+        uses: actions/checkout@v4
+        with:
+          path: mingw-w64
+      - name: Build the mingw-w64 runtime
+        run: |
+          PREFIX=$(pwd)/prefix/${{matrix.arch}}-w64-mingw32
+          cd mingw-w64/mingw-w64-headers
+          autoreconf
+          mkdir build
+          cd build
+          ../configure --prefix=$PREFIX --host=${{matrix.arch}}-w64-mingw32 --with-default-msvcrt=${{matrix.crt}}
+          make install
+          cd ../../mingw-w64-crt
+          autoreconf
+          mkdir build
+          cd build
+          ../configure --prefix=$PREFIX --host=${{matrix.arch}}-w64-mingw32 --with-default-msvcrt=${{matrix.crt}} ${{ matrix.arch == 'i686' && '--enable-lib32 --disable-lib64' || '--disable-lib32 --enable-lib64' }}
+          make -j$(nproc)
+          make install
+          cd ../../mingw-w64-libraries/winpthreads
+          autoreconf
+          mkdir build
+          cd build
+          ../configure --prefix=$PREFIX --host=${{matrix.arch}}-w64-mingw32
+          make -j$(nproc)
+          make install
+      - name: Build the GCC runtimes
+        run: |
+          cd gcc-*
+          cd build
+          make -j$(nproc)
+          make install-strip
+      - name: Package the toolchain
+        run: |
+          NAME=gcc-mingw-${{matrix.crt}}-${{matrix.arch}}
+          mv prefix $NAME
+          tar -Jcf $NAME.tar.xz --format=ustar --numeric-owner --owner=0 --group=0 --sort=name $NAME
+      - uses: actions/upload-artifact@v4
+        with:
+          name: linux-${{matrix.crt}}-${{matrix.arch}}-gcc-toolchain
+          path: |
+            gcc-mingw-*.tar.xz
+          retention-days: 7
+
+  gcc-cross:
+    runs-on: ubuntu-latest
+    needs: [gcc]
+    strategy:
+      fail-fast: false
+      matrix:
+        crt:
+          - ucrt
+          - msvcrt
+        arch:
+          - i686
+          - x86_64
+    steps:
+      - uses: actions/download-artifact@v4
+        with:
+          name: linux-${{matrix.crt}}-${{matrix.arch}}-gcc-toolchain
+      - name: Unpack cross toolchain
+        run: |
+          tar -Jxf gcc-mingw-*.tar.xz
+          rm gcc-mingw-*.tar.xz
+          sudo mv gcc-mingw* /opt/gcc-mingw
+          echo /opt/gcc-mingw/bin >> $GITHUB_PATH
+      - name: Build dependencies
+        run: |
+          PREFIX=$(pwd)/prefix
+
+          curl -LO https://ftp.gnu.org/gnu/gmp/gmp-6.3.0.tar.xz
+          tar -Jxf gmp-*.tar.xz
+          rm gmp-*.tar.xz
+          cd gmp-*
+          mkdir build
+          cd build
+          ../configure --prefix=$PREFIX --host=${{matrix.arch}}-w64-mingw32 --disable-shared
+          make -j$(nproc)
+          make install
+          cd ../..
+
+          curl -LO https://ftp.gnu.org/gnu/mpfr/mpfr-4.2.1.tar.xz
+          tar -Jxf mpfr-*.tar.xz
+          rm mpfr-*.tar.xz
+          cd mpfr-*
+          mkdir build
+          cd build
+          ../configure --prefix=$PREFIX --host=${{matrix.arch}}-w64-mingw32 --disable-shared --with-gmp=$PREFIX
+          make -j$(nproc)
+          make install
+          cd ../..
+
+          curl -LO https://ftp.gnu.org/gnu/mpc/mpc-1.3.1.tar.gz
+          tar -zxf mpc-*.tar.gz
+          rm mpc-*.tar.gz
+          cd mpc-*
+          mkdir build
+          cd build
+          ../configure --prefix=$PREFIX --host=${{matrix.arch}}-w64-mingw32 --disable-shared --with-gmp=$PREFIX
+          make -j$(nproc)
+          make install
+          cd ../..
+
+      - name: Build binutils
+        run: |
+          curl -LO https://ftp.gnu.org/gnu/binutils/binutils-2.42.tar.xz
+          tar -Jxf binutils-*.tar.xz
+          rm binutils-*.tar.xz
+          cd binutils-*
+          mkdir build
+          cd build
+          ../configure --prefix=$(pwd)/../../prefix --host=${{matrix.arch}}-w64-mingw32 --target=${{matrix.arch}}-w64-mingw32 --disable-werror --disable-multilib
+          make -j$(nproc)
+          make install-strip
+          echo $(pwd)/../../prefix/bin >> $GITHUB_PATH
+      - name: Build GCC
+        run: |
+          curl -LO https://ftp.gnu.org/gnu/gcc/gcc-14.1.0/gcc-14.1.0.tar.xz
+          tar -Jxf gcc-*.tar.xz
+          rm gcc-*.tar.xz
+          cd gcc-*
+          mkdir build
+          cd build
+          ../configure --prefix=$(pwd)/../../prefix --host=${{matrix.arch}}-w64-mingw32 --target=${{matrix.arch}}-w64-mingw32 --enable-languages=c,c++ --disable-multilib --enable-threads=posix --with-gmp=$(pwd)/../../prefix --with-native-system-header-dir=/opt/gcc-mingw/${{matrix.arch}}-w64-mingw32/include --disable-bootstrap
+          make -j$(nproc) all-gcc
+          make install-strip-gcc
+      - name: Transplant the mingw-w64 installation from the cross compiler to the native one
+        run: |
+          rm -rf prefix/${{matrix.arch}}-w64-mingw32/include
+          rm -rf prefix/${{matrix.arch}}-w64-mingw32/lib
+          mkdir -p prefix/${{matrix.arch}}-w64-mingw32/bin
+          cp -a /opt/gcc-mingw/${{matrix.arch}}-w64-mingw32/bin/*.dll prefix/${{matrix.arch}}-w64-mingw32/bin
+          cp -a /opt/gcc-mingw/${{matrix.arch}}-w64-mingw32/include prefix/${{matrix.arch}}-w64-mingw32
+          cp -a /opt/gcc-mingw/${{matrix.arch}}-w64-mingw32/lib prefix/${{matrix.arch}}-w64-mingw32/lib
+          cp -a /opt/gcc-mingw/${{matrix.arch}}-w64-mingw32/include/c++ prefix/include
+          cp -a /opt/gcc-mingw/${{matrix.arch}}-w64-mingw32/bin/*.dll prefix/bin
+          cp -a /opt/gcc-mingw/${{matrix.arch}}-w64-mingw32/lib/*.dll prefix/bin
+          rm -rf prefix/lib/gcc
+          cp -a /opt/gcc-mingw/lib/gcc prefix/lib
+      - name: Package the toolchain
+        run: |
+          NAME=gcc-mingw-${{matrix.crt}}-${{matrix.arch}}
+          mv prefix $NAME
+          zip -9rq $NAME.zip $NAME
+      - uses: actions/upload-artifact@v4
+        with:
+          name: windows-${{matrix.crt}}-${{matrix.arch}}-gcc-toolchain
+          path: |
+            gcc-mingw-*.zip
+          retention-days: 7
+
+  test-gcc:
+    needs: [gcc-cross]
+    runs-on: windows-latest
+    strategy:
+      fail-fast: false
+      matrix:
+        crt:
+          - ucrt
+          - msvcrt
+        arch:
+          - i686
+          - x86_64
+    steps:
+      - uses: actions/download-artifact@v4
+        with:
+          name: windows-${{matrix.crt}}-${{matrix.arch}}-gcc-toolchain
+      - name: Unpack toolchain
+        run: |
+          Expand-Archive gcc-mingw-*.zip -DestinationPath .
+          del gcc-mingw-*.zip
+          mv gcc-mingw-* c:\gcc-mingw
+          echo "c:\gcc-mingw\bin" | Out-File -FilePath $Env:GITHUB_PATH -Encoding utf8 -Append
+      - name: Check out llvm-mingw tests
+        uses: actions/checkout@v4
+        with:
+          repository: mstorsjo/llvm-mingw
+          ref: 20250402
+      - name: Run tests
+        run: |
+          g++ test/hello.c -o hello.exe
+          ./hello.exe
+          gcc test/crt-test.c -o crt-test.exe
+          ./crt-test.exe
+          g++ test/hello-cpp.cpp -o hello-cpp.exe
+          ./hello-cpp.exe
+          g++ test/hello-exception.cpp -o hello-exception.exe
+          ./hello-exception.exe