name: CMake

on:
  workflow_dispatch: # Manual trigger
  push:
    branches:
      - master
  pull_request:
    paths-ignore:
      - .gitignore
      - .github/**
      - '!.github/workflows/build-cmake.yaml'  # Run check on self change
      - CONTRIBUTORS
      - LICENSE
      - NOTICE
      - README.md
      - android/**
      - iphone/**
      - data/countries-strings/**
      - data/sound-strings/**
      - docs/**
      - packaging/**
      - pyhelpers/**
      - tools/**
      - '!tools/python/test_server/**'
      - xcode/**

# Cancels previous jobs if the same branch or PR was updated again.
concurrency:
  group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
  cancel-in-progress: true

jobs:
  build:
    strategy:
      fail-fast: false
      matrix:
        cmake-build-type: [ Debug, Release ]
        environment:
          - os: ubuntu-24.04
            cc: clang-19
            cxx: clang++-19
            unity: OFF
            run-tests: OFF

          - os: ubuntu-24.04
            cc: clang-19
            cxx: clang++-19

          - os: ubuntu-24.04
            cc: gcc-14
            cxx: g++-14

          - os: ubuntu-24.04
            cc: gcc-13
            cxx: g++-13

          - os: macos-26
            cc: clang
            cxx: clang++
            developer-dir: /Applications/Xcode_26.2.app/Contents/Developer
        exclude:
          - environment: { unity: OFF }
            cmake-build-type: Release

    name: "${{ matrix.environment.os }} ${{ matrix.environment.cc }} ${{ matrix.cmake-build-type }}${{ matrix.environment.unity == 'OFF' && ' No Unity' || '' }}"

    runs-on: ${{ matrix.environment.os }}

    env:
      BUILD_DIR: build
      DEVELOPER_DIR: ${{ matrix.environment.developer-dir }}

    steps:
      - name: Free disk space by removing .NET, Android and Haskell
        if: ${{ runner.os == 'Linux' }}
        run: sudo rm -rf /usr/share/dotnet /usr/local/lib/android /opt/ghc

      - name: Checkout sources
        uses: actions/checkout@v4

      - name: Restore Boost submodule from cache
        uses: actions/cache@v4
        with:
          path: |
            3party/boost
            .git/modules/3party/boost
          key: boost-submodule

      - name: Parallel submodules checkout
        run: git submodule update --depth 1 --init --recursive --jobs=20

      - name: Install build tools and dependencies (Linux)
        if: ${{ runner.os == 'Linux' }}
        run: |
          sudo apt update -y
          sudo apt install -y \
              clang-19 \
              libgl1-mesa-dev \
              libglvnd-dev \
              libharfbuzz-dev \
              libqt6svg6-dev \
              libxcursor-dev \
              libxi-dev \
              libxinerama-dev \
              libxrandr-dev \
              ninja-build \
              qt6-base-dev \
              qt6-positioning-dev \

      - name: Install build tools and dependencies (macOS)
        if: ${{ runner.os == 'macOS' }}
        env:
          HOMEBREW_NO_INSTALLED_DEPENDENTS_CHECK: 1
          HOMEBREW_NO_ANALYTICS: 1
          HOMEBREW_NO_INSTALL_CLEANUP: 1
        run: |
          brew install ninja qt@6
          pip3 install tornado --break-system-packages

      - name: Configure repository
        run: ./configure.sh

      - name: Configure ccache
        uses: hendrikmuhs/ccache-action@v1.2
        with:
          key: ${{ github.workflow }}-${{ matrix.environment.os }}-${{ matrix.environment.cc }}-${{ matrix.environment.unity }}-${{ matrix.cmake-build-type }}

      - name: Configure cmake
        env:
          CC: ${{ matrix.environment.cc }}
          CXX: ${{ matrix.environment.cxx }}
          CMAKE_C_COMPILER_LAUNCHER: ccache
          CMAKE_CXX_COMPILER_LAUNCHER: ccache
          UNITY_BUILD: ${{ matrix.environment.unity || 'ON' }}
        run: |
          cmake . -B ${{ env.BUILD_DIR }} -G Ninja \
            -DCMAKE_BUILD_TYPE=${{ matrix.cmake-build-type }} \
            -DCMAKE_C_FLAGS=-g1 \
            -DCMAKE_CXX_FLAGS=-g1 \
            -DCMAKE_UNITY_BUILD=${UNITY_BUILD}

      - name: Compile
        working-directory: ${{ env.BUILD_DIR }}
        run: ninja

      - name: Prepare testing environment (Linux)
        if: ${{ runner.os == 'Linux' }}
        run: |
          sudo locale-gen en_US
          sudo locale-gen en_US.UTF-8
          sudo locale-gen es_ES
          sudo locale-gen es_ES.UTF-8
          sudo locale-gen fr_FR
          sudo locale-gen fr_FR.UTF-8
          sudo locale-gen ru_RU
          sudo locale-gen ru_RU.UTF-8
          sudo update-locale

      - name: Run tests
        if: ${{ matrix.environment.run-tests != 'OFF' }}
        working-directory: ${{ env.BUILD_DIR }}
        env:
          # drape_tests - see next step
          # generator_integration_tests - https://github.com/organicmaps/organicmaps/issues/225
          # opening_hours_integration_tests - https://github.com/organicmaps/organicmaps/issues/219
          # opening_hours_supported_features_tests - https://github.com/organicmaps/organicmaps/issues/219
          # routing_integration_tests - https://github.com/organicmaps/organicmaps/issues/221
          # shaders_tests - https://github.com/organicmaps/organicmaps/issues/223
          # world_feed_integration_tests - https://github.com/organicmaps/organicmaps/issues/215
          CTEST_EXCLUDE_REGEX: "drape_tests|generator_integration_tests|opening_hours_integration_tests|opening_hours_supported_features_tests|routing_benchmarks|routing_integration_tests|routing_quality_tests|search_quality_tests|storage_integration_tests|shaders_tests|world_feed_integration_tests"
        run: ctest -L "omim-test" -E "$CTEST_EXCLUDE_REGEX" --output-on-failure

      # Run drape tests separately. They require offscreen rendering support.
      # Setting QT_QPA_PLATFORM to "offscreen" breaks network tests on macOS.
      - name: Run drape tests
        if: ${{ matrix.environment.run-tests != 'OFF' }}
        working-directory: ${{ env.BUILD_DIR }}
        env:
          QT_QPA_PLATFORM: "offscreen"
        run: ctest -R drape_tests --output-on-failure
