# Copyright (C) 2021 Sebastian Pipping <sebastian@pipping.org>
# Licensed under the MIT license

name: Build and test (Linux)

on:
  pull_request:
  push:
  schedule:
    - cron: '0 4 * * 5'  # Every Friday at 4am

jobs:
  build_and_test:
    name: Build and test (Linux)
    strategy:
      matrix:
        include:
          - name: Native Linux
            cmake_args: >-
              -DCMAKE_C_COMPILER=clang-21
              -DCMAKE_CXX_COMPILER=clang++-21
            cflags: >-
              -fsanitize=address,undefined,leak
              -fno-sanitize-recover=all
              -fno-omit-frame-pointer
            ldflags: >-
              -fsanitize=address,undefined,leak
          - name: MinGW on Linux
            cmake_args: >-
              -DCMAKE_C_COMPILER=i686-w64-mingw32-gcc
              -DCMAKE_CXX_COMPILER=i686-w64-mingw32-g++
              -DCMAKE_SYSTEM_NAME=Windows
              -DWIN32=ON
              -DMINGW=ON
    runs-on: ubuntu-24.04
    steps:
      - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd  # v6.0.2

      - name: Add Clang/LLVM repositories (Non-MinGW)
        if: "${{ ! contains(matrix.cmake_args, 'mingw') }}"
        run: |-
          set -x
          source /etc/os-release
          wget -O - https://apt.llvm.org/llvm-snapshot.gpg.key | sudo apt-key add -
          sudo add-apt-repository "deb http://apt.llvm.org/${UBUNTU_CODENAME}/ llvm-toolchain-${UBUNTU_CODENAME}-21 main"

      - name: Install build dependencies
        run: |-
          set -x
          sudo apt-get update
          sudo apt-get install --yes --no-install-recommends -V \
              cmake \
              doxygen \
              graphviz \
              lzip \
              qhelpgenerator-qt5 \
              qtchooser

      - name: Install build dependencies (MinGW)
        if: "${{ contains(matrix.cmake_args, 'mingw') }}"
        run: |-
          set -x

          # Install 32bit Wine
          sudo dpkg --add-architecture i386  # for wine32
          sudo apt-get update  # again, due to new architecture
          sudo apt-get install --yes --no-install-recommends -V \
              mingw-w64 \
              wine-stable \
              wine32:i386

      - name: Install build dependencies (Non-MinGW)
        if: "${{ ! contains(matrix.cmake_args, 'mingw') }}"
        run: |-
          sudo apt-get install --yes --no-install-recommends -V \
              clang-21 \
              libclang-rt-21-dev

      - name: Build, test and install
        run: |-
          set -x
          sed 's,:,\n,g' <<<"${PATH}"
          cmake --version

          GTEST_VERSION=1.8.1
          GTEST_PREFIX=~/.local/

          wget https://github.com/google/googletest/archive/release-${GTEST_VERSION}.tar.gz
          tar xf release-${GTEST_VERSION}.tar.gz
          (
            cd googletest-release-${GTEST_VERSION}/

            # Silence warning "Compatibility with CMake < 3.10 will be removed"
            find -name CMakeLists.txt -print -exec sed 's/cmake_minimum_required.*/cmake_minimum_required(VERSION 3.10.0)/' -i {} \;

            cmake \
                -DBUILD_SHARED_LIBS=ON \
                -DCVF_VERSION=${GTEST_VERSION} \
                -DCMAKE_INSTALL_PREFIX:PATH=${GTEST_PREFIX} \
                ${{ matrix.cmake_args }} \
                .
            make
            make install
          )

          mkdir build
          pushd build
            compile_flags=(
              -pipe

              -O1
              -g
              ${{ matrix.cflags }}

              -Wall
              -Wextra
              -pedantic
            )
            CFLAGS="${compile_flags[*]} -std=c99"
            CXXFLAGS="${compile_flags[*]} -std=c++11"
            LDFLAGS='-g ${{ matrix.ldflags }}'
            cmake_args=(
              -DCMAKE_INSTALL_PREFIX:PATH=${GTEST_PREFIX}

              -Wdev
              -Werror=dev
              -Wdeprecated
              -Werror=deprecated

              -DCMAKE_C_FLAGS="${CFLAGS}"
              -DCMAKE_CXX_FLAGS="${CXXFLAGS}"
              -DCMAKE_EXE_LINKER_FLAGS="${LDFLAGS}"
              -DCMAKE_MODULE_LINKER_FLAGS="${LDFLAGS}"
              -DCMAKE_SHARED_LINKER_FLAGS="${LDFLAGS}"

              ${{ matrix.cmake_args }}

              -DURIPARSER_BUILD_TESTS=ON
              -DURIPARSER_WARNINGS_AS_ERRORS=ON
            )
            cmake "${cmake_args[@]}" -DCMAKE_INSTALL_INCLUDEDIR=include123 ..

            make VERBOSE=1 all

            # NOTE: We need to copy some .dll files next to the
            #       Windows binaries so that they are ready to be executed
            if [[ "${{ matrix.cmake_args }}" == *mingw* ]]; then
              cp /usr/lib/gcc/i686-w64-mingw32/*-posix/libgcc_s_dw2-1.dll ./
              cp /usr/lib/gcc/i686-w64-mingw32/*-posix/libstdc++-6.dll ./
              cp /usr/i686-w64-mingw32/lib/libwinpthread-1.dll ./
              cp "${GTEST_PREFIX}"/bin/libgtest.dll ./
            fi

            # Configure UBSan to show (non-default) stack traces for runtime errors
            # NOTE: "halt_on_error=1" we don't need to add because of the
            #       -fno-sanitize-recover=all for CFLAGS further up.
            # NOTE: "abort_on_error=1" we don't need here because to CI,
            #       a non-zero exit code is all that matters.
            export UBSAN_OPTIONS='print_stacktrace=1'

            make VERBOSE=1 test ARGS=--verbose
            cat Testing/Temporary/LastTest.log

            make install
            make DESTDIR="${PWD}"/ROOT/ install
            find ROOT | sort

            ./doc/release.sh
          popd
          pushd cmake/test_find_package
            cmake "${cmake_args[@]}" .
            make VERBOSE=1
            if [[ "${{ matrix.cmake_args }}" == *mingw* ]]; then
              cp "${GTEST_PREFIX}"/bin/liburiparser-1.dll ./
              wine ./hello.exe
            else
              ./hello
            fi
          popd

          git fetch --force --tags --unshallow origin  # for "git describe" in make-distcheck.sh

          GTEST_PREFIX="${GTEST_PREFIX}" \
            ./make-distcheck.sh \
            -DCMAKE_INSTALL_PREFIX:PATH=${GTEST_PREFIX} \
            ${{ matrix.cmake_args }}

          ! git status | fgrep -A100 'Untracked files:'  # works best at the very end
