name: macos

concurrency:
  group: ${{ github.workflow }}-${{ github.ref }}
  cancel-in-progress: true

on: [push, pull_request]

defaults:
  run:
    shell: bash

jobs:

  macos:

    strategy:
      fail-fast: false
      matrix:
        include:
          - image: '13'
            platform: 'x86-64'
            xcode_version: '15.2'
            deployment_target: '10.15'
          - image: '14'
            platform: 'ARM64'
            xcode_version: '15.4'
            deployment_target: '11.0'

    name: "macOS ${{ matrix.image }} ${{ matrix.platform }} 🔨${{ matrix.xcode_version }} 🎯${{ matrix.deployment_target }}"

    runs-on: "macos-${{ matrix.image }}"

    env:
      # Bump first number to reset all caches.
      CACHE_KEY: "1-macOS-${{ matrix.image }}-${{ matrix.platform }}-XC${{ matrix.xcode_version }}-DT${{ matrix.deployment_target }}"
      CLICOLOR_FORCE: '1'
      MACOSX_DEPLOYMENT_TARGET: ${{ matrix.deployment_target }}
      MAKEFLAGS: 'OUTPUT_DIR=build INSTALL_DIR=install TARGET=macos'

    steps:

      # Install dependencies. {{{

      - name: XCode version
        run: |
          sudo xcode-select -s /Applications/Xcode_${{ matrix.xcode_version }}.app
          xcodebuild -version
          xcode-select -p

      - name: Setup Python
        uses: actions/setup-python@v5
        with:
          python-version: '3.12'

      - name: Install dependencies
        run: |
          set -x
          python3 -m pip install --disable-pip-version-check meson ruamel.yaml
          wget -O ninjatracing.zip https://github.com/nico/ninjatracing/archive/a669e3644cf22b29cbece31dbed2cfbf34e5f48e.zip
          unzip -j ninjatracing.zip '*/ninjatracing'
          install -m755 ninjatracing /usr/local/bin/
          rm ninjatracing*
          # Install brew packages.
          packages=(
            autoconf
            automake
            bash
            binutils
            cmake
            coreutils
            findutils
            libtool
            make
            nasm
            ninja
            p7zip
            pkg-config
            sdl2
            util-linux
          )
          # Don't auto-update.
          export HOMEBREW_NO_AUTO_UPDATE=1
          # Don't upgrade already installed formulas.
          export HOMEBREW_NO_INSTALL_UPGRADE=1
          # Remove some installed packages to prevent brew
          # from attempting (and failing) to upgrade them.
          brew uninstall gradle maven
          brew install --formula --overwrite --quiet "${packages[@]}"

      - name: Update PATH
        run: >
          printf '%s\n'
          "$(brew --prefix)/opt/findutils/libexec/gnubin"
          "$(brew --prefix)/opt/make/libexec/gnubin"
          "$(brew --prefix)/opt/util-linux/bin"
          | tee "${GITHUB_PATH}"

      # }}}

      # Checkout / fetch. {{{

      - name: Checkout
        uses: actions/checkout@v4
        with:
          clean: false
          fetch-depth: 0
          filter: tree:0
          show-progress: false

      - name: Fetch
        run: make fetchthirdparty

      # }}}

      # Restore / setup caches. {{{

      - name: Generate cache key
        run: make TARGET= cache-key

      - name: Restore build directory
        id: build-restore
        uses: actions/cache/restore@v4
        with:
          path: build
          key: ${{ env.CACHE_KEY }}-build-${{ hashFiles('cache-key') }}

      - name: Restore build cache
        id: ccache-restore
        if: steps.build-restore.outputs.cache-hit != 'true'
        uses: actions/cache/restore@v4
        with:
          path: /Users/runner/Library/Caches/ccache
          key: ${{ env.CACHE_KEY }}-ccache-${{ hashFiles('cache-key') }}
          restore-keys: ${{ env.CACHE_KEY }}-ccache-

      - name: Install ccache
        if: steps.build-restore.outputs.cache-hit != 'true'
        run: |
          wget --progress=dot:mega https://github.com/ccache/ccache/releases/download/v4.10.2/ccache-4.10.2-darwin.tar.gz
          tar xf ccache-4.10.2-darwin.tar.gz
          printf '%s\n' "$PWD/ccache-4.10.2-darwin" >>"${GITHUB_PATH}"

      - name: Setup build cache
        if: steps.build-restore.outputs.cache-hit != 'true'
        run: |
          set -x
          which ccache
          ccache --version
          ccache --zero-stats
          ccache --max-size=256M
          ccache --show-config

      # }}}

      # Build. {{{

      - name: Build
        id: build
        if: steps.build-restore.outputs.cache-hit != 'true'
        run: make base

      - name: Dump build timings
        if: contains('failure success', steps.build.conclusion) && !cancelled()
        run: make buildstats

      # }}}

      # Clean / save caches. {{{

      - name: Clean caches
        if: contains('failure success', steps.build.conclusion) && !cancelled()
        run: |
          set -x
          # Trim the build directory.
          rm -rf build/{cmake,staging,thirdparty}
          ccache --cleanup >/dev/null
          ccache --show-stats --verbose

      - name: Save build cache
        uses: actions/cache/save@v4
        if: steps.build-restore.outputs.cache-hit != 'true' && steps.ccache-restore.outputs.cache-hit != 'true'
        with:
          path: /Users/runner/Library/Caches/ccache
          key: ${{ steps.ccache-restore.outputs.cache-primary-key }}

      - name: Save build directory
        uses: actions/cache/save@v4
        if: steps.build-restore.outputs.cache-hit != 'true'
        with:
          path: build
          key: ${{ steps.build-restore.outputs.cache-primary-key }}

      # }}}

      # Dump & check binaries. {{{

      - name: Dump binaries runtime path & dependencies
        run: make bininfo

      - name: Checking binaries for missing dependencies
        run: make bincheck

      # }}}

      - name: Test
        run: ./base/utils/fake_tty.py make --assume-old=base testfront

      # Generate / upload artifact. {{{

      - name: Generate artifact
        # Note: ensure the build skeleton is created, so there are no dangling
        # symlinks (e.g. `data/dict`) to trip 7zip during artifact generation…
        run: make skeleton update --assume-old=base

      - name: Upload artifact
        uses: actions/upload-artifact@v4
        with:
          name: koreader-macos-${{ matrix.platform }}
          path: '*.7z'

      # }}}

# vim: foldmethod=marker foldlevel=0
