name: build

on:
  push:
    branches: [ "main" ]
  pull_request:
    branches: [ "main" ]
  workflow_dispatch:

env:
  CARGO_TERM_COLOR: always

jobs:
  linux:
    name: Build Linux (GNU)
    runs-on: ubuntu-latest
    strategy:
      matrix:
        include:
          - target: x86_64
            target_triple: x86_64-unknown-linux-gnu
            apt_packages: ""
            custom_env: {}
          - target: i686
            target_triple: i686-unknown-linux-gnu
            apt_packages: crossbuild-essential-i386
            custom_env:
              CC: i686-linux-gnu-gcc
              CXX: i686-linux-gnu-g++
              CARGO_TARGET_I686_UNKNOWN_LINUX_GNU_LINKER: i686-linux-gnu-g++
              RUSTC_LINKER: i686-linux-gnu-g++
          - target: aarch64
            target_triple: aarch64-unknown-linux-gnu
            apt_packages: crossbuild-essential-arm64
            custom_env:
              CFLAGS_aarch64_unknown_linux_gnu: -D__ARM_ARCH=8
              CC: aarch64-linux-gnu-gcc
              CXX: aarch64-linux-gnu-g++
              CARGO_TARGET_AARCH64_UNKNOWN_LINUX_GNU_LINKER: aarch64-linux-gnu-g++
              RUSTC_LINKER: aarch64-linux-gnu-g++
          - target: armv7
            target_triple: armv7-unknown-linux-gnueabihf
            apt_packages: crossbuild-essential-armhf
            custom_env:
              CC: arm-linux-gnueabihf-gcc
              CXX: arm-linux-gnueabihf-g++
              CARGO_TARGET_ARMV7_UNKNOWN_LINUX_GNUEABIHF_LINKER: arm-linux-gnueabihf-g++
              RUSTC_LINKER: arm-linux-gnueabihf-g++
    steps:
      - uses: actions/checkout@v4

      - name: Install base dependencies on Ubuntu
        run: |
          sudo apt-get update
          sudo apt-get install -y build-essential cmake perl pkg-config libclang-dev musl-tools

      - name: Install target-specific APT dependencies
        if: ${{ matrix.apt_packages != '' }}
        run: |
          sudo apt-get update
          sudo apt-get install -y ${{ matrix.apt_packages }}

      - name: Add Rust target
        run: rustup target add ${{ matrix.target_triple }}

      - name: Build for ${{ matrix.target }}
        env: ${{ matrix.custom_env }}
        run: cargo build --release --target ${{ matrix.target_triple }}

      - name: Archive build artifacts
        run: |
          cd target/${{ matrix.target_triple }}/release
          zip -r ../../../build-linux-${{ matrix.target }}.zip *
        working-directory: ${{ github.workspace }}

      - name: Upload build artifact
        uses: actions/upload-artifact@v4
        with:
          name: build-linux-${{ matrix.target }}
          path: build-linux-${{ matrix.target }}.zip
          retention-days: 1

  musllinux:
    name: Build Linux (musl)
    runs-on: ubuntu-latest
    strategy:
      matrix:
        include:
          - target: x86_64
            target_triple: x86_64-unknown-linux-musl
            package: x86_64-linux-musl-cross
            apt_packages: ""
            custom_env:
              CC: x86_64-linux-musl-gcc
              CXX: x86_64-linux-musl-g++
              CARGO_TARGET_X86_64_UNKNOWN_LINUX_MUSL_LINKER: x86_64-linux-musl-g++
              RUSTC_LINKER: x86_64-linux-musl-g++
          - target: aarch64
            target_triple: aarch64-unknown-linux-musl
            package: aarch64-linux-musl-cross
            apt_packages: crossbuild-essential-arm64
            custom_env:
              CC: aarch64-linux-musl-gcc
              CXX: aarch64-linux-musl-g++
              CARGO_TARGET_AARCH64_UNKNOWN_LINUX_MUSL_LINKER: aarch64-linux-musl-g++
              RUSTC_LINKER: aarch64-linux-musl-g++
          - target: i686
            target_triple: i686-unknown-linux-musl
            package: i686-linux-musl-cross
            apt_packages: crossbuild-essential-i386
            custom_env:
              CC: i686-linux-musl-gcc
              CXX: i686-linux-musl-g++
              CARGO_TARGET_I686_UNKNOWN_LINUX_MUSL_LINKER: i686-linux-musl-g++
              RUSTC_LINKER: i686-linux-musl-g++
          - target: armv7
            target_triple: armv7-unknown-linux-musleabihf
            package: armv7l-linux-musleabihf-cross
            apt_packages: crossbuild-essential-armhf
            custom_env:
              CC: armv7l-linux-musleabihf-gcc
              CXX: armv7l-linux-musleabihf-g++
              CARGO_TARGET_ARMV7_UNKNOWN_LINUX_MUSLEABIHF_LINKER: armv7l-linux-musleabihf-g++
              RUSTC_LINKER: armv7l-linux-musleabihf-g++

    steps:
      - uses: actions/checkout@v4

      - name: Install base dependencies on Ubuntu
        run: |
          sudo apt-get update
          sudo apt-get install -y build-essential cmake perl pkg-config libclang-dev musl-tools

      - name: Install target-specific APT dependencies
        if: ${{ matrix.apt_packages != '' }}
        run: |
          sudo apt-get update
          sudo apt-get install -y ${{ matrix.apt_packages }}

      - name: Prepare musl cross-compiler
        run: |
          curl -O http://musl.cc/${{ matrix.package }}.tgz
          tar xzf ${{ matrix.package }}.tgz -C /opt
          echo "/opt/${{ matrix.package }}/bin/" >> $GITHUB_PATH

      - name: Add Rust target
        run: rustup target add ${{ matrix.target_triple }}

      - name: Build for ${{ matrix.target }}
        env: ${{ matrix.custom_env }}
        run: cargo build --release --target ${{ matrix.target_triple }}

      - name: Archive build artifacts
        run: |
          cd target/${{ matrix.target_triple }}/release
          zip -r ../../../build-musllinux-${{ matrix.target }}.zip *
        working-directory: ${{ github.workspace }}

      - name: Upload build artifact
        uses: actions/upload-artifact@v4
        with:
          name: build-musllinux-${{ matrix.target }}
          path: build-musllinux-${{ matrix.target }}.zip
          retention-days: 1

  windows:
    name: Build Windows
    runs-on: windows-latest
    strategy:
      matrix:
        include:
          - target: x86_64
            target_triple: x86_64-pc-windows-msvc
          - target: i686
            target_triple: i686-pc-windows-msvc
    steps:
      - uses: actions/checkout@v4

      - name: Install dependencies on Windows
        run: |
          choco install cmake -y
          choco install strawberryperl -y
          choco install pkgconfiglite -y
          choco install llvm -y
          choco install nasm -y
        shell: cmd

      - name: Build on Windows with Static Linking
        env:
          RUSTFLAGS: "-C target-feature=+crt-static"
        run: cargo build --release --target ${{ matrix.target_triple }}

      - name: Archive build artifacts
        shell: pwsh
        run: |
          Compress-Archive -Path 'target\${{ matrix.target_triple }}\release\*' -DestinationPath "build-windows-${{ matrix.target }}.zip" -CompressionLevel Optimal -Force
        working-directory: ${{ github.workspace }}

      - name: Upload build artifact
        uses: actions/upload-artifact@v4
        with:
          name: build-windows-${{ matrix.target }}
          path: build-windows-${{ matrix.target }}.zip
          retention-days: 1

  macos:
    name: Build macOS
    strategy:
      matrix:
        include:
          - target: x86_64
            runner: macos-latest
            target_triple: x86_64-apple-darwin
          - target: aarch64
            runner: macos-latest
            target_triple: aarch64-apple-darwin
    runs-on: ${{ matrix.runner }}
    steps:
      - uses: actions/checkout@v4

      - name: Install dependencies on macOS
        run: |
          brew update
          brew install --formula cmake pkg-config llvm

      - name: Add Rust target
        run: rustup target add ${{ matrix.target_triple }}

      - name: Build for ${{ matrix.target }}
        run: cargo build --release --target ${{ matrix.target_triple }}

      - name: Archive build artifacts
        run: |
          cd target/${{ matrix.target_triple }}/release
          zip -r ../../../build-macos-${{ matrix.target }}.zip *
        working-directory: ${{ github.workspace }}

      - name: Upload build artifact
        uses: actions/upload-artifact@v4
        with:
          name: build-macos-${{ matrix.target }}
          path: build-macos-${{ matrix.target }}.zip
          retention-days: 1
