name: Cross Compile CI
on:
  pull_request_target:
  push:
    tags:
      - '*'
    branches:
      - 'master'
      - 'ci-tests/**'  # Branch namespace can be used to test changes to test before going to master
jobs:
  build:
    runs-on: ${{ matrix.os }}
    strategy:
      fail-fast: false
      matrix:
        # This is the matrix. They form permutations.
        triplet: [""]
        preset: [android-armeabi-v7a-vcpkg, android-arm64-v8a-vcpkg, android-x86-vcpkg, android-x86_64-vcpkg]
        os: [ubuntu-24.04]
        # These are additional individual jobs. There are no permutations of these.
        include:
          - triplet: x86-linux
            os: ubuntu-24.04
            preset: ninja-multi-vcpkg
            setup: |
              sudo dpkg --add-architecture i386
              sudo apt-get update
              sudo apt-get install -y gcc-multilib g++-multilib libx11-dev:i386 libxext-dev:i386 libgl1-mesa-dev:i386 libglu1-mesa-dev:i386 libtool autoconf libc6-dev-i386 libgpg-error-dev:i386 libltdl-dev:i386
            additional_args: "`-DCMAKE_C_FLAGS=-m32`, `-DCMAKE_CXX_FLAGS=-m32`, `-DOPENBLACK_CROSSCOMPILING=ON`"
          - triplet: arm64-linux
            os: ubuntu-24.04
            preset: ninja-multi-vcpkg
            setup: |
              sudo dpkg --add-architecture arm64
              # Specify amd64 for exisitng azure.archive.ubuntu.com sources
              sudo sed -i '/^Types: deb/ a Architectures: amd64' /etc/apt/sources.list.d/ubuntu.sources
              # Add arm64 source from azure.ports.ubuntu.com because the architecture isn't on archive
              sudo cp /etc/apt/sources.list.d/ubuntu.sources /etc/apt/sources.list.d/ubuntu-arm64.sources
              sudo sed -i 's,http://azure.archive.ubuntu.com/ubuntu/,http://azure.ports.ubuntu.com/,g' /etc/apt/sources.list.d/ubuntu-arm64.sources
              sudo sed -i 's,Architectures: amd64,Architectures: arm64,g' /etc/apt/sources.list.d/ubuntu-arm64.sources
              # Install the arch dependencies
              sudo apt-get update
              sudo apt-get install -y gcc-aarch64-linux-gnu g++-aarch64-linux-gnu libx11-dev:arm64 libxext-dev:arm64 libgl1-mesa-dev:arm64 libglu1-mesa-dev:arm64
            additional_args: "`-DCMAKE_C_COMPILER=aarch64-linux-gnu-gcc`, `-DCMAKE_CXX_COMPILER=aarch64-linux-gnu-g++`, `-DCMAKE_C_FLAGS=-march=armv8-a`, `-DCMAKE_CXX_FLAGS=-march=armv8-a`, `-DOPENBLACK_CROSSCOMPILING=ON`"
          # TODO(#638): Many of the emscripten dependencies conflict due to pthreads
          # - preset: emscripten-vcpkg
          #   os: ubuntu-latest
          #   setup: |
          #     git clone https://github.com/emscripten-core/emsdk ${EMSDK}
          #     cd ${EMSDK}
          #     ./emsdk install latest
          #     ./emsdk activate latest
          - triplet: x86-windows
            os: windows-latest
            preset: ninja-multi-vcpkg
          - triplet: arm64-windows
            os: windows-latest
            preset: ninja-multi-vcpkg
          - os: macos-latest
            preset: ios-arm64-vcpkg

    env:
      VCPKG_DEFAULT_TRIPLET: ${{ matrix.triplet }}
      EMSDK: '/tmp/emsdk/upstream/emscripten'

    steps:
      - uses: actions/checkout@v4
        with:
          ref: ${{ github.event.pull_request.head.ref }}
          repository: ${{ github.event.pull_request.head.repo.full_name }}
          submodules: recursive

      - name: Add base repo to git config
        run: git remote add upstream ${{ github.event.pull_request.base.repo.html_url }}
        if: startsWith(github.event_name, 'pull_request')

      # TODO(https://github.com/bkaradzic/bgfx.cmake/issues/242): Android and Emscripten wants opengl installed on system to build bgfx
      - name: Setup (Android and Emscripten and Linux)
        run: |
          sudo apt update -y
          sudo apt install -y libgl1-mesa-dev libglu1-mesa-dev
          echo "ANDROID_NDK_HOME=$ANDROID_NDK_LATEST_HOME" >> $GITHUB_ENV # to use C++23 on 26.2.11394342
        if: (startsWith(matrix.preset, 'android') || startsWith(matrix.preset, 'emscripten')) || startsWith(matrix.os, 'ubuntu')

      - name: Setup
        run: ${{ matrix.setup }}
        if: matrix.setup

      # Setup the build machine with the most recent versions of CMake and Ninja. Both are cached if not already: on subsequent runs both will be quickly restored from GitHub cache service.
      - uses: lukka/get-cmake@latest

      - name: Restore from cache and setup vcpkg executable and data files.
        uses: lukka/run-vcpkg@v11
        with:
          vcpkgJsonGlob: 'vcpkg.json'

      - name: Run CMake+vcpkg to build packages.
        id: build-packages
        uses: lukka/run-cmake@v10
        with:
          configurePreset: '${{ matrix.preset }}'
          configurePresetAdditionalArgs: "[`-DOPENBLACK_WARNINGS_AS_ERRORS=ON`${{ matrix.triplet && format(', `-DVCPKG_TARGET_TRIPLET={0}`', matrix.triplet) }}${{ matrix.additional_args && format(', {0}', matrix.additional_args) }}]"

      - name: Upload logs if failed
        if: failure()
        uses: actions/upload-artifact@v4
        with:
          name: vcpkg-build-logs-${{ matrix.triplet || matrix.preset }}
          path: vcpkg/buildtrees/*/*.log

      - name: Run CMake+Ninja to build the code (Debug).
        uses: lukka/run-cmake@v10
        with:
          buildPreset: '${{ matrix.preset }}-debug'

      - name: Run CMake+vcpkg to build the code (Release).
        uses: lukka/run-cmake@v10
        with:
          buildPreset: '${{ matrix.preset }}-release'

      - run: echo "GITHUB_REF_NAME_DASHES=${GITHUB_REF_NAME/\//-}" >> $GITHUB_ENV
        shell: bash

      - uses: actions/upload-artifact@v4
        with:
          name: openblack-${{ matrix.triplet || matrix.preset }}-${{ env.GITHUB_REF_NAME_DASHES }}
          path: cmake-build-presets/${{ matrix.preset }}/bin
          if-no-files-found: error

  assemble-android-apk:
    needs: build
    runs-on: ${{ matrix.os }}
    strategy:
      fail-fast: false
      matrix:
        # This is the matrix. They form permutations.
        os: [ ubuntu-latest, windows-latest ]
    steps:
      - uses: actions/checkout@v4
        with:
          ref: ${{ github.event.pull_request.head.ref }}
          repository: ${{ github.event.pull_request.head.repo.full_name }}
      - name: Add base repo to git config
        run: git remote add upstream ${{ github.event.pull_request.base.repo.html_url }}
        if: startsWith(github.event_name, 'pull_request')
      - uses: actions/setup-java@v4
        with:
          distribution: 'temurin'
          java-version: '11'
      - run: echo "GITHUB_REF_NAME_DASHES=${GITHUB_REF_NAME/\//-}" >> $GITHUB_ENV
        shell: bash
      - uses: actions/download-artifact@v4
        name: Download pre-compiled android-armeabi-v7a-vcpkg
        with:
          name: openblack-android-armeabi-v7a-vcpkg-${{ env.GITHUB_REF_NAME_DASHES }}
          path: android/app/src/main/jniLibs/armeabi-v7a
      - uses: actions/download-artifact@v4
        name: Download pre-compiled android-arm64-v8a-vcpkg
        with:
          name: openblack-android-arm64-v8a-vcpkg-${{ env.GITHUB_REF_NAME_DASHES }}
          path: android/app/src/main/jniLibs/arm64-v8a
      - uses: actions/download-artifact@v4
        name: Download pre-compiled android-x86-vcpkg
        with:
          name: openblack-android-x86-vcpkg-${{ env.GITHUB_REF_NAME_DASHES }}
          path: android/app/src/main/jniLibs/x86
      - uses: actions/download-artifact@v4
        name: Download pre-compiled android-x86_64-vcpkg
        with:
          name: openblack-android-x86_64-vcpkg-${{ env.GITHUB_REF_NAME_DASHES }}
          path: android/app/src/main/jniLibs/x86_64
      - name: Move downloads around
        shell: bash
        run: |
          mkdir -p android/app/src/main/jniLibs/{debug,release}/{armeabi-v7a,arm64-v8a,x86,x86_64}
          mv android/app/src/main/jniLibs/armeabi-v7a/Debug/libopenblack_lib.so    android/app/src/main/jniLibs/debug/armeabi-v7a
          mv android/app/src/main/jniLibs/armeabi-v7a/Release/libopenblack_lib.so  android/app/src/main/jniLibs/release/armeabi-v7a
          mv android/app/src/main/jniLibs/arm64-v8a/Debug/libopenblack_lib.so      android/app/src/main/jniLibs/debug/arm64-v8a
          mv android/app/src/main/jniLibs/arm64-v8a/Release/libopenblack_lib.so    android/app/src/main/jniLibs/release/arm64-v8a
          mv android/app/src/main/jniLibs/x86/Debug/libopenblack_lib.so            android/app/src/main/jniLibs/debug/x86
          mv android/app/src/main/jniLibs/x86/Release/libopenblack_lib.so          android/app/src/main/jniLibs/release/x86
          mv android/app/src/main/jniLibs/x86_64/Debug/libopenblack_lib.so         android/app/src/main/jniLibs/debug/x86_64
          mv android/app/src/main/jniLibs/x86_64/Release/libopenblack_lib.so       android/app/src/main/jniLibs/release/x86_64
          find android/app/src/main/jniLibs
      - name: Setup Gradle
        uses: gradle/actions/setup-gradle@v3
        with:
          build-root-directory: ./android
      - name: Build with Gradle (Debug)
        run: ./gradlew build --no-daemon assembleDebug -PusePrebuiltNativeLibs
        working-directory: ./android
      - name: Write signing key
        id: write_key
        uses: timheuer/base64-to-file@v1.2
        with:
          fileName: 'keystore/signing_keystore.jks'
          encodedString: ${{ secrets.ANDROID_SIGNING_STORE_KEY_B64 }}
      - name: Build with Gradle (Release)
        run: ./gradlew build --no-daemon assembleRelease -PusePrebuiltNativeLibs
        working-directory: ./android
        env:
          STORE_KEY: ${{ steps.write_key.outputs.filePath }}
          STORE_PASSWORD: ${{ secrets.ANDROID_SIGNING_STORE_PASSWORD }}
          STORE_KEY_ALIAS: ${{ secrets.ANDROID_SIGNING_STORE_KEY_ALIAS }}
          STORE_KEY_PASSWORD: ${{ secrets.ANDROID_SIGNING_STORE_PASSWORD }}
      - uses: actions/upload-artifact@v4
        with:
          name: openblack-android-apk-${{ env.GITHUB_REF_NAME_DASHES }}
          path: android/app/build/outputs/apk
          if-no-files-found: error
          overwrite: true
