name: C/C++ CI

on: [push, pull_request]

jobs:
  build:
    name: ${{ matrix.config.name }}
    runs-on: ${{ matrix.config.os }}

    defaults:
      run:
        shell: ${{ matrix.config.shell }}

    env:
      CCACHE_DIR: ${{ github.workspace }}/.ccache

    strategy:
      matrix:
        config:
          - {name: i686-pc-windows-msvc, os: windows-latest, shell: cmd, arch: x86, cmakeArgs: -G Ninja, buildType: Release}
          - {name: apple-darwin, os: macos-latest, shell: sh, cmakeArgs: -G Xcode -DAPPLE_BREAKPAD=ON, destDir: osx, buildType: RelWithDebInfo}
          - {name: apple-ios, os: macos-latest, shell: sh, cmakeArgs: -DCMAKE_SYSTEM_NAME=iOS -G Xcode, destDir: ios, buildType: Release}
          - {name: x86_64-pc-linux-gnu, os: ubuntu-20.04, shell: sh, cmakeArgs: -G Ninja, destDir: linux, buildType: RelWithDebInfo}
          - {name: x86_64-pc-windows-msvc, os: windows-latest, shell: cmd, arch: x64, cmakeArgs: -G Ninja, buildType: Release}
          - {name: x86_64-w64-mingw32, os: windows-latest, shell: 'msys2 {0}', cmakeArgs: -G Ninja, destDir: win, buildType: RelWithDebInfo}
          - {name: libretro-x86_64-pc-linux-gnu, os: ubuntu-latest, shell: sh, cmakeArgs: -DLIBRETRO=ON -DCMAKE_POSITION_INDEPENDENT_CODE=TRUE -G Ninja, buildType: Release}
          - {name: libretro-x86_64-w64-mingw32, os: windows-latest, shell: 'msys2 {0}', cmakeArgs: -DLIBRETRO=ON -G Ninja, buildType: Release}

    steps:
      - name: Set up build environment (macOS)
        run: |
          # Unlink and re-link to prevent errors when github mac runner images install python outside of brew. See https://github.com/actions/setup-python/issues/577
          brew list -1 | grep python | while read formula; do brew unlink $formula; brew link --overwrite $formula; done
          brew update || :
          brew install libao ldid ninja pulseaudio
          VULKAN_VER=1.3.261.1 && aria2c https://sdk.lunarg.com/sdk/download/$VULKAN_VER/mac/vulkansdk-macos-$VULKAN_VER.dmg
          hdiutil attach ./vulkansdk-macos-*.dmg -mountpoint /Volumes/VulkanSDK
          sudo /Volumes/VulkanSDK/InstallVulkan.app/Contents/MacOS/InstallVulkan --root $HOME/VulkanSDK --accept-licenses --default-answer --confirm-command install
          hdiutil detach /Volumes/VulkanSDK
          echo "VULKAN_SDK=$HOME/VulkanSDK/macOS" >> $GITHUB_ENV
        if: runner.os == 'macOS'

      - name: Set up build environment (Linux)
        run: |
          sudo add-apt-repository ppa:christianrauch/libdecoration
          sudo apt-get update
          sudo apt-get -y install ccache libao-dev libasound2-dev libevdev-dev libgl1-mesa-dev liblua5.3-dev libminiupnpc-dev libpulse-dev libsdl2-dev libudev-dev libzip-dev ninja-build libcurl4-openssl-dev
          sudo apt-get -y install libwayland-dev libdecor-0-dev libaudio-dev libjack-dev libsndio-dev libsamplerate0-dev libx11-dev libxext-dev libxrandr-dev libxcursor-dev libxfixes-dev libxi-dev libxss-dev libxkbcommon-dev libdrm-dev libgbm-dev libgles2-mesa-dev libegl1-mesa-dev libdbus-1-dev libibus-1.0-dev libudev-dev fcitx-libs-dev
        if: runner.os == 'Linux'

      - name: Set up build environment (Windows, MinGW)
        uses: msys2/setup-msys2@v2
        with:
          msystem: MINGW64
          install: git make mingw-w64-x86_64-ccache mingw-w64-x86_64-cmake mingw-w64-x86_64-lua mingw-w64-x86_64-ninja mingw-w64-x86_64-SDL2 mingw-w64-x86_64-toolchain
        if: matrix.config.shell == 'msys2 {0}'

      - name: Set up build environment (Windows, Visual Studio)
        run: |
          choco install ccache directx-sdk ninja
          echo DXSDK_DIR=C:\Program Files (x86)\Microsoft DirectX SDK (June 2010)>> %GITHUB_ENV%
        if: matrix.config.shell == 'cmd'

      - uses: ilammy/msvc-dev-cmd@v1
        with:
          arch: ${{ matrix.config.arch }}
        if: matrix.config.shell == 'cmd'

      - uses: actions/checkout@v3
        with:
          fetch-depth: 0
          submodules: true

      - name: Compile a universal OpenMP (macOS)
        run: HOMEBREW_NO_INSTALLED_DEPENDENTS_CHECK=1 brew reinstall --build-from-source --formula ./shell/apple/libomp.rb
        if: matrix.config.name == 'apple-darwin'

      - name: Compile OpenMP.xcframework (iOS)
        run: ./shell/apple/emulator-ios/OpenMP/build_ios_openmp.sh --disableSimulator
        if: matrix.config.name == 'apple-ios'

      - uses: actions/cache@v3
        with:
          path: ${{ env.CCACHE_DIR }}
          key: ccache-${{ matrix.config.name }}-${{ github.sha }}
          restore-keys: ccache-${{ matrix.config.name }}-
        if: runner.os != 'macOS'

      - name: CMake
        run: |
          cmake -B build -DCMAKE_BUILD_TYPE=${{ matrix.config.buildType }} -DCMAKE_INSTALL_PREFIX=artifact ${{ matrix.config.cmakeArgs }} -DSENTRY_UPLOAD_URL=${{ env.SENTRY_UPLOAD_URL }}
          cmake --build build --config ${{ matrix.config.buildType }} --target install
        env:
          SENTRY_UPLOAD_URL: ${{ secrets.SENTRY_UPLOAD_URL }}

      - name: Unit Tests
        run: |
          cmake -B build -DCMAKE_BUILD_TYPE=${{ matrix.config.buildType }} -DCMAKE_INSTALL_PREFIX=artifact -DENABLE_CTEST=ON ${{ matrix.config.cmakeArgs }}
          cmake --build build --config ${{ matrix.config.buildType }}
          ./build/flycast
        if: matrix.config.name == 'x86_64-pc-linux-gnu'

      - name: Dump symbols
        run: |
          mkdir -p symbols
          core/deps/breakpad/bin/dump_syms artifact/bin/flycast.exe > symbols/flycast.sym 2>/dev/null
          strip artifact/bin/flycast.exe
        if: matrix.config.name == 'x86_64-w64-mingw32'

      - name: Build breakpad (linux)
        working-directory: core/deps/breakpad
        run: |
          ./configure
          make
          sudo make install
        if: matrix.config.name == 'x86_64-pc-linux-gnu'

      - name: Dump symbols and make AppImage (linux)
        run: |
          mkdir -p symbols
          dump_syms artifact/bin/flycast > symbols/flycast.sym 2>/dev/null
          strip artifact/bin/flycast
          shell/linux/make-appimage.sh . artifact/bin appimage
          mv flycast-x86_64.AppImage artifact/bin
          rm artifact/bin/flycast
        if: matrix.config.name == 'x86_64-pc-linux-gnu'

      - uses: actions/upload-artifact@v3
        with:
          name: flycast-${{ matrix.config.name }}
          path: artifact/bin

      - name: Package app (macos)
        run: |
          cd artifact/bin
          zip -rm flycast.app.zip Flycast.app
        if: matrix.config.name == 'apple-darwin'

      - name: Package app (windows)
        run: |
          powershell Compress-Archive artifact/bin/flycast.exe artifact/bin/flycast.zip 
          rm artifact/bin/flycast.exe
        if: matrix.config.name == 'x86_64-w64-mingw32'

      - name: Configure AWS Credentials
        id: aws-credentials
        uses: aws-actions/configure-aws-credentials@v2
        with:
          aws-access-key-id: AKIAJOZQS4H2PHQWYFCA
          aws-secret-access-key: ${{ secrets.S3_SECRET_KEY }}
          aws-region: us-east-2
        if: github.repository == 'flyinghead/flycast' && github.event_name == 'push' && matrix.config.destDir != ''

      - name: Upload to S3
        run: aws s3 sync artifact/bin s3://flycast-builds/${{ matrix.config.destDir }}/${GITHUB_REF#refs/}-$GITHUB_SHA --acl public-read --follow-symlinks
        shell: bash
        if: ${{ steps.aws-credentials.outputs.aws-account-id != '' }}

      - name: Setup Sentry CLI
        uses: mathieu-bour/setup-sentry-cli@v1
        env:
          SENTRY_TOKEN: ${{ secrets.SENTRY_TOKEN }}
        with:
          url: https://sentry.io
          token: ${{ env.SENTRY_TOKEN }}
          organization: flycast
          project: minidump
        if: ${{ env.SENTRY_TOKEN != '' }}
      
      - name: Upload symbols to Sentry (Windows, macOS, Linux)
        run: |
          VERSION=$(git describe --tags --always)
          sentry-cli releases new "$VERSION"
          sentry-cli releases set-commits "$VERSION" --auto
          sentry-cli debug-files upload symbols
        shell: bash
        env:
          SENTRY_TOKEN: ${{ secrets.SENTRY_TOKEN }}
        if: ${{ env.SENTRY_TOKEN != '' && (matrix.config.name == 'x86_64-w64-mingw32' || matrix.config.name == 'apple-darwin' || matrix.config.name == 'x86_64-pc-linux-gnu') }}
        