name: build
on: [push, pull_request]
jobs:
  client:
    runs-on: ubuntu-latest
    strategy:
      fail-fast: false
      matrix:
        compiler:
          - {cc: gcc, cxx: g++}
          - {cc: clang, cxx: clang++}
        wayland_shell: [xdg-shell, libdecor]
        build_type: [Release, Debug]
    steps:
    - uses: actions/checkout@v5
      with:
        submodules: recursive
    - name: Update apt
      run: |
        sudo apt-get update
    - name: Install client dependencies
      run: |
        sudo apt-get install \
          weston libgtest-dev \
          libdw-dev libunwind-dev \
          libspice-protocol-dev nettle-dev \
          libgl-dev libgles-dev \
          libx11-dev libxss-dev libxi-dev libxinerama-dev libxcursor-dev libxpresent-dev \
          libwayland-dev libxkbcommon-dev \
          libfontconfig-dev \
          libsamplerate0-dev libpipewire-0.3-dev libpulse-dev \
          $([ '${{ matrix.wayland_shell }}' = libdecor ] && echo 'libdecor-0-dev libdbus-1-dev') \
          $([ '${{ matrix.compiler.cc }}' = clang ] && echo 'clang-tools')
        sudo pip3 install pyenchant
    - name: Configure client
      env:
        CC: /usr/bin/${{ matrix.compiler.cc }}
        CXX: /usr/bin/${{ matrix.compiler.cxx }}
      run: |
        mkdir client/build
        cd client/build
        cmake \
          -DCMAKE_BUILD_TYPE=${{ matrix.build_type }} \
          -DCMAKE_LINKER:FILEPATH=/usr/bin/ld \
          -DCMAKE_EXPORT_COMPILE_COMMANDS=ON \
          -DENABLE_LIBDECOR=${{ matrix.wayland_shell == 'libdecor' }}  \
          -DENABLE_TESTS=ON \
          -DOPTIMIZE_FOR_NATIVE=OFF \
          ..
    - name: Build client
      run: |
        cd client/build
        make -j$(nproc)
    - name: Checking help spelling
      run: ./client/build/looking-glass-client --help | ./doc/lgspell.py
    - name: Check GL function calls
      if: matrix.compiler.cc == 'clang'
      run: WAYLAND_SHELL='${{ matrix.wayland_shell }}' ./gl-check
    - name: Package client build
      run: tar -cf client-build.tar -C client build
    - name: Upload client build
      uses: actions/upload-artifact@v6
      with:
        name: client-build-${{ matrix.compiler.cc }}-${{ matrix.wayland_shell }}-${{ matrix.build_type }}
        path: client-build.tar
        retention-days: 1

  module:
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v5
      with:
        submodules: recursive
    - name: Build kernel module
      run: |
        cd module
        make

  host-linux:
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v5
      with:
        submodules: recursive
    - name: Update apt
      run: |
        sudo apt-get update
    - name: Install Linux host dependencies
      run: |
        sudo apt-get install libdw-dev libunwind-dev libglib2.0-dev \
          libxcb-xfixes0-dev libpipewire-0.3-dev libxcb-shm0-dev
    - name: Configure Linux host
      run: |
        mkdir host/build
        cd host/build
        cmake ..
    - name: Build Linux host
      run: |
        cd host/build
        make -j$(nproc)

  host-windows-cross:
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v5
      with:
        submodules: recursive
    - name: Update apt
      run: |
        sudo apt-get update
    - name: Install Windows host cross-compile dependencies
      run: |
        sudo apt-get install gcc-mingw-w64-x86-64 g++-mingw-w64-x86-64 nsis
    - name: Configure Windows host for cross-compile
      run: |
        mkdir host/build
        cd host/build
        cmake -DCMAKE_TOOLCHAIN_FILE=../toolchain-mingw64.cmake ..
    - name: Cross-compile Windows host
      run: |
        cd host/build
        make -j$(nproc)
    - name: Build Windows host installer
      run: |
        cd host/build
        makensis platform/Windows/installer.nsi
    - name: Build Windows host installer with IVSHMEM drivers
      run: |
        cd host/build
        curl https://dl.quantum2.xyz/ivshmem.tar.gz | tar xz
        makensis -DIVSHMEM platform/Windows/installer.nsi

  host-windows-native:
    runs-on: windows-2025
    steps:
    - uses: actions/checkout@v5
      with:
        submodules: recursive
    - name: Install NSIS
      shell: powershell
      run: |
        winget install -e --id NSIS.NSIS --silent --accept-source-agreements --accept-package-agreements
        $paths = @(
          (Join-Path ${env:ProgramFiles}      'NSIS\Bin'),
          (Join-Path ${env:ProgramFiles(x86)} 'NSIS\Bin')
        ) | Where-Object { Test-Path $_ }

        if ($paths.Count -eq 0) {
          Write-Error "NSIS 'Bin' folder not found after install."
          exit 1
        }

        $paths | ForEach-Object {
          Add-Content -Path $env:GITHUB_PATH -Value $_
        }

        Write-Host "makensis location(s): $($paths -join ', ')"
    - name: Test NSIS
      run: |
        makensis /VERSION
    - name: Configure Windows host for native MinGW-w64
      run: |
        mkdir host\build
        cd host\build
        cmake -G "MinGW Makefiles" ..
    - name: Build Windows host on native MinGW-w64
      run: |
        cd host\build
        mingw32-make "-j$([Environment]::ProcessorCount)"
    - name: Build Windows host installer
      run: |
        cd host\build
        makensis -DBUILD_32BIT platform\Windows\installer.nsi

  idd:
    runs-on: windows-2022
    steps:
    - uses: actions/checkout@v5
      with:
        submodules: recursive
    - name: Add msbuild to PATH
      uses: microsoft/setup-msbuild@v3
      with:
        msbuild-architecture: x64
    - name: Install NuGet packages
      run: |
        cd idd
        nuget restore LGIdd.sln
    - name: Build IDD
      run: |
        cd idd
        msbuild.exe LGIdd.sln /t:Build /p:Configuration=Release /p:Platform=x64
    - name: Build NSIS Installer
      run: |
        cd idd\x64\Release\LGIdd
        makensis -DBUILD_32BIT installer.nsi
    - name: Build NSIS installer with IVSHMEM drivers
      run: |
        cd idd\x64\Release
        Invoke-WebRequest https://dl.quantum2.xyz/ivshmem.tar.gz -OutFile ivshmem.tar.gz
        tar -xzvf ivshmem.tar.gz
        cd LGIdd
        makensis -DBUILD_32BIT -DIVSHMEM installer.nsi

  obs:
    runs-on: ubuntu-latest
    strategy:
      matrix:
        cc: [gcc, clang]
    steps:
    - uses: actions/checkout@v5
      with:
        submodules: recursive
    - name: Update apt
      run: |
        sudo apt-get update
    - name: Install obs plugin dependencies
      run: |
        sudo apt-get install libdw-dev libunwind-dev libobs-dev libgl1-mesa-dev
    - name: Configure obs plugin
      run: |
        mkdir obs/build
        cd obs/build
        CC=/usr/bin/${{ matrix.cc }} cmake \
          -DOPTIMIZE_FOR_NATIVE=OFF \
          ..
    - name: Build obs plugin
      run: |
        cd obs/build
        make -j$(nproc)

  docs:
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v5
      with:
        submodules: recursive
    - name: Update apt
      run: |
        sudo apt-get update
    - name: Install docs dependencies
      run: |
        sudo apt-get install python3-sphinx python3-sphinx-rtd-theme \
            python3-sphinxcontrib.spelling
    - name: Build docs
      run: |
        cd doc
        make dirhtml SPHINXOPTS='-b spelling -W' -j$(nproc)

  client-tests:
    needs: client
    runs-on: ubuntu-latest
    strategy:
      fail-fast: false
      matrix:
        compiler:
          - {cc: gcc, cxx: g++}
          - {cc: clang, cxx: clang++}
        wayland_shell: [xdg-shell, libdecor]
        build_type: [Release, Debug]
    steps:
      - uses: actions/checkout@v5
        with:
          submodules: recursive

      - name: Install dependencies
        run: |
          sudo apt-get update
          sudo apt-get install \
            weston libgtest-dev libgl1-mesa-dri \
            libdecor-0-dev libdbus-1-dev \
            libdw-dev libunwind-dev \
            libspice-protocol-dev nettle-dev \
            libgl-dev libgles-dev \
            libx11-dev libxss-dev libxi-dev libxinerama-dev \
            libxcursor-dev libxpresent-dev \
            libwayland-dev libxkbcommon-dev libfontconfig-dev \
            libsamplerate0-dev libpipewire-0.3-dev libpulse-dev

      - name: Download client build
        uses: actions/download-artifact@v7
        with:
          name: client-build-${{ matrix.compiler.cc }}-${{ matrix.wayland_shell }}-${{ matrix.build_type }}
          path: client-build

      - name: Run client tests
        id: tests
        run: |
          tar -xf client-build/client-build.tar -C client
          ctest --test-dir client/build --output-on-failure

      - name: Upload client test failures
        if: failure() && steps.tests.outcome == 'failure'
        uses: actions/upload-artifact@v6
        with:
          name: client-test-failures-${{ matrix.compiler.cc }}-${{ matrix.wayland_shell }}-${{ matrix.build_type }}
          path: |
            client/build/Testing/
            /tmp/lg-render-case.*
