name: libbinio autotools CI

on:
  - push
  - pull_request

jobs:
  build:

    strategy:

      matrix:
        os: [ubuntu-latest, macos-latest]
        compiler: [gcc, clang]
        include:
          - compiler: gcc-4.8 # To test compatibility with older systems
            os: ubuntu-latest
          - compiler: djgpp-2.0.5-gcc-12.2.0 # To test compatibility for Adplay - DOS
            os: ubuntu-latest
          - compiler: djgpp-2.0.5-gcc-4.8.5 # To test compatibility for Adplay - DOS
            os: ubuntu-latest
          - compiler: mingw-w64 # To test Windows builds with Wine
            os: ubuntu-latest
          - compiler: powerpc-gcc # To test compatibility with big-endian powerpc
            os: ubuntu-latest
          - compiler: powerpc64-gcc # To test compatibility with big-endian powerpc
            os: ubuntu-latest
          - compiler: powerpcle64-gcc # To test compatibility with little-endian powerpc
            os: ubuntu-latest

      fail-fast: false

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

    steps:
    - uses: actions/checkout@v7

    - name: Install packages (Linux)
      if: ${{ runner.os == 'Linux' }}
      run: |
        sudo apt update
        sudo apt install -y texlive-latex-base texinfo

        if [[ ${{ matrix.compiler }} == "clang" ]]; then
          sudo apt install -y build-essential clang
        fi

        if [[ ${{ matrix.compiler }} == "gcc-4.8" ]]; then
          wget http://archive.ubuntu.com/ubuntu/pool/universe/g/gcc-4.8/g++-4.8_4.8.5-4ubuntu8_amd64.deb
          wget http://archive.ubuntu.com/ubuntu/pool/universe/g/gcc-4.8/libstdc++-4.8-dev_4.8.5-4ubuntu8_amd64.deb
          wget http://archive.ubuntu.com/ubuntu/pool/universe/g/gcc-4.8/gcc-4.8-base_4.8.5-4ubuntu8_amd64.deb
          wget http://archive.ubuntu.com/ubuntu/pool/universe/g/gcc-4.8/gcc-4.8_4.8.5-4ubuntu8_amd64.deb
          wget http://archive.ubuntu.com/ubuntu/pool/universe/g/gcc-4.8/libgcc-4.8-dev_4.8.5-4ubuntu8_amd64.deb
          wget http://archive.ubuntu.com/ubuntu/pool/universe/g/gcc-4.8/cpp-4.8_4.8.5-4ubuntu8_amd64.deb
          wget http://archive.ubuntu.com/ubuntu/pool/universe/g/gcc-4.8/libasan0_4.8.5-4ubuntu8_amd64.deb
          sudo apt install ./gcc-4.8_4.8.5-4ubuntu8_amd64.deb ./gcc-4.8-base_4.8.5-4ubuntu8_amd64.deb ./libstdc++-4.8-dev_4.8.5-4ubuntu8_amd64.deb ./cpp-4.8_4.8.5-4ubuntu8_amd64.deb ./libgcc-4.8-dev_4.8.5-4ubuntu8_amd64.deb ./libasan0_4.8.5-4ubuntu8_amd64.deb ./g++-4.8_4.8.5-4ubuntu8_amd64.deb
        fi

        if [[ ${{ matrix.compiler }} = djgpp* ]]; then
          # Flex is required, but even though it's in the GitHub runner image, and marked as installed
          # it's still missing some things, see https://github.com/orgs/community/discussions/45029
          sudo apt install -y libfl2 libfl-dev software-properties-common
          # Install dosemu2 for testing
          sudo add-apt-repository -y ppa:dosemu2/ppa
          sudo apt install -y dosemu2 unzip
          # We need CWSDPMI as well if we want to run any DOS programs.
          wget https://www.delorie.com/pub/djgpp/current/v2misc/csdpmi7b.zip
          unzip -j -o "csdpmi7b.zip" "bin/CWSDPMI.EXE" -d ./test

          if [[ ${{ matrix.compiler }} == "djgpp-2.0.5-gcc-12.2.0" ]]; then
            wget https://github.com/andrewwutw/build-djgpp/releases/download/v3.4/djgpp-linux64-gcc1220.tar.bz2
            bzcat djgpp-linux64-gcc1220.tar.bz2 | sudo tar -x --directory /usr/local
          fi
          if [[ ${{ matrix.compiler }} == "djgpp-2.0.5-gcc-4.8.5" ]]; then
            wget https://github.com/andrewwutw/build-djgpp/releases/download/v1.6/djgpp-linux64-gcc485.tar.bz2
            bzcat djgpp-linux64-gcc485.tar.bz2 | sudo tar -x --directory /usr/local
          fi
        fi

        if [[ ${{ matrix.compiler }} == "mingw-w64" ]]; then
          sudo apt install -y g++-mingw-w64-x86-64 wine64 libwine gcc-mingw-w64-x86-64-win32-runtime gcc-mingw-w64-x86-64-win32 g++-mingw-w64-x86-64-win32
        fi

        if [[ ${{ matrix.compiler }} = powerpc-gcc ]]; then
          sudo apt install -y g++-powerpc-linux-gnu gcc-powerpc-linux-gnu qemu-user
        fi
        if [[ ${{ matrix.compiler }} = powerpc64-gcc ]]; then
          # qemu does not support powerpc64
          sudo apt install -y g++-powerpc64-linux-gnu gcc-powerpc64-linux-gnu
        fi
        if [[ ${{ matrix.compiler }} = powerpcle64-gcc ]]; then
          sudo apt install -y g++-powerpc64le-linux-gnu gcc-powerpc64le-linux-gnu qemu-user
        fi

    - name: Install packages (macOS)
      if: ${{ runner.os == 'macOS' }}
      run: |
        # Allow core dumps
        sudo sh -c 'touch /cores/test && rm /cores/test && chmod -R 0777 /cores'
        brew update
        # See comment in 'make' step (this takes good 20 mins)
        #brew install --cask mactex-no-gui
        brew install automake texinfo libtool

    # - name: Install LLVM and Clang (Linux)
    #   if: ${{ matrix.compiler == 'clang' && runner.os != 'macOS' }}
    #   uses: KyleMayes/install-llvm-action@v1
    #   with:
    #     version: "10.0"

# compile_env   is for `libbinio` configure and make distcheck
# compile_opts  is for `libbinio` configure

    - name: Set GCC environment (Linux)
      if: ${{ matrix.compiler == 'gcc' && runner.os == 'Linux'}}
      run: |
        echo 'compile_env=CFLAGS="-O2 -pipe -fsanitize=address -fsanitize=leak" CXXFLAGS="-O2 -pipe -fsanitize=address -fsanitize=leak" CPPFLAGS="-fsanitize=address -fsanitize=leak" LDFLAGS="-Wl,-O1 -Wl,--as-needed -Wl,--gc-sections"' >> $GITHUB_ENV

    - name: Set GCC-4.8 environment (Linux)
      if: ${{ matrix.compiler == 'gcc-4.8' }}
      run: echo 'compile_env=CC=gcc-4.8 CXX=g++-4.8' >> $GITHUB_ENV

    - name: Set GCC environment (macOS)
      if: ${{ matrix.compiler == 'gcc' && runner.os == 'macOS' }}
      run: echo 'compile_env=CC=gcc CXX=g++' >> $GITHUB_ENV

    - name: Set Clang environment
      if: ${{ matrix.compiler == 'clang' }}
      run: echo 'compile_env=CC=clang CXX=clang++' >> $GITHUB_ENV

    - name: Set DJGPP environment
      if: ${{ startsWith(matrix.compiler, 'djgpp') }}
      run: |
        echo 'compile_opts=--host=i586-pc-msdosdjgpp --prefix=/usr/local/djgpp' >> $GITHUB_ENV
        echo 'compile_env=CFLAGS="-O2 -pipe" CXXFLAGS="-O2 -pipe -Wno-deprecated" CPPFLAGS="-O2 -pipe -Wno-deprecated" LDFLAGS="-Wl,-O1 -Wl,--as-needed -Wl,--no-undefined -Wl,--gc-sections" PKG_CONFIG_PATH=/usr/local/djgpp/lib/pkgconfig' >> $GITHUB_ENV
        echo '/usr/local/djgpp/bin/' >> $GITHUB_PATH

    - name: Set MinGW environment
      if: ${{ matrix.compiler == 'mingw-w64' }}
      run: |
        echo 'compile_opts=--host=x86_64-w64-mingw32 --prefix=/usr/local/x86_64-w64-mingw32 CXXFLAGS=-Wno-deprecated CPPFLAGS=-Wno-deprecated PKG_CONFIG_PATH=/usr/local/x86_64-w64-mingw32/lib/pkgconfig' >> $GITHUB_ENV
        if command -v wine64 >/dev/null 2>&1; then
          echo "WINE=$(command -v wine64)" >> $GITHUB_ENV
          echo "LOG_COMPILER=$(command -v wine64)" >> $GITHUB_ENV
        elif command -v wine >/dev/null 2>&1; then
          echo "WINE=$(command -v wine)" >> $GITHUB_ENV
          echo "LOG_COMPILER=$(command -v wine)" >> $GITHUB_ENV
        else
          echo "wine64/wine is not available" >&2
          exit 1
        fi
        echo "WINEPATH=/usr/x86_64-w64-mingw32/bin:/usr/lib/gcc/x86_64-w64-mingw32/10-win32:/usr/local/x86_64-w64-mingw32/bin:${{ github.workspace }}/src/.libs:${{ github.workspace }}/test/.libs" >> $GITHUB_ENV
        echo "testdir=${{ github.workspace }}/test" >> $GITHUB_ENV

    - name: Set PowerPC-GCC environment
      if: ${{ matrix.compiler == 'powerpc-gcc' }}
      run: |
        echo 'compile_opts=--host=powerpc-linux-gnu --prefix=/usr/local/powerpc' >> $GITHUB_ENV
        echo 'compile_env=PKG_CONFIG_PATH=/usr/local/powerpc/lib/pkgconfig MAKE="make stresstest_wrapper=./qemu-wrapper.sh"'>> $GITHUB_ENV
        echo -e '#!/bin/sh\nexec qemu-ppc -L /usr/local/powerpc -L /usr/powerpc-linux-gnu "$@"' > qemu-wrapper.sh
        chmod 755 qemu-wrapper.sh

    - name: Set PowerPC64-GCC environment
      if: ${{ matrix.compiler == 'powerpc64-gcc' }}
      run: |
        echo 'compile_opts=--host=powerpc64-linux-gnu --prefix=/usr/local/powerpc64'>> $GITHUB_ENV
        echo 'compile_env=PKG_CONFIG_PATH=/usr/local/powerpc64/lib/pkgconfig' >> $GITHUB_ENV
        #qmeu does not support powerpc64
        #echo -e '#!/bin/sh\nexec qemu-ppc -L /usr/local/powerpc64 -L /usr/powerpc64-linux-gnu "$@"' > qemu-wrapper.sh
        #chmod 755 qemu-wrapper.sh

    - name: Set PowerPC64LE-GCC environment
      if: ${{ matrix.compiler == 'powerpc64le-gcc' }}
      run: |
        echo 'compile_opts=--host=powerpc64le-linux-gnu --prefix=/usr/local/powerpc64le'>> $GITHUB_ENV
        echo 'compile_env=PKG_CONFIG_PATH=/usr/local/powerpc64le/lib/pkgconfig MAKE="make stresstest_wrapper=./qemu-wrapper.sh"'>> $GITHUB_ENV
        echo -e '#!/bin/sh\nexec qemu-ppc -L /usr/local/powerpc64le -L /usr/powerpc64le-linux-gnu "$@"' > qemu-wrapper.sh
        chmod 755 qemu-wrapper.sh

    - name: autoreconf
      run: autoreconf -i
    - name: configure
      run: ./configure ${{ env.compile_opts }} ${{ env.compile_env }} || cat config.log

    # make distcheck ensure that it is possible build in an external build-directory, and perform `make check`.
    # The later fail for cross-builds is due to the need for running scripts that needs to be patched.
    # Also distcheck fails on macOS due to missing LaTeX, so restrict to Linux only.
    - name: make distcheck
      if: ${{ matrix.compiler == 'gcc' && runner.os == 'Linux' }}
      env:
        DISTCHECK_CONFIGURE_FLAGS: "${{ env.compile_opts }} ${{ env.compile_env }}"
      run: |
        make distcheck ${{ env.compile_env }}

    - name: make
      run: |
        ulimit -c unlimited -S
        make all ${{ env.compile_env }} && sudo env PATH=$PATH make install

        # cross-platform needs to patch the helper scripts for `make check`, so please prepare them - and patch them
        #if  [[ ${{ matrix.compiler }} == "powerpc-gcc" ]]; then
        #  make test/crctest test/emutest test/playtest test/strstest ${{ env.compile_env }}
        #  sed -e 's/exec "/exec qemu-ppc -L \/usr\/local\/powerpc -L \/usr\/powerpc-linux-gnu "/' -i test/crctest test/emutest test/playtest test/strstest
        #elif  [[ ${{ matrix.compiler }} == "powerpc64-gcc" ]]; then
        #  make test/crctest test/emutest test/playtest test/strstest ${{ env.compile_env }}
        #  sed -e 's/exec "/exec qemu-ppc -L \/usr\/local\/powerpc64 -L \/usr\/powerpc64-linux-gnu "/' -i test/crctest test/emutest test/playtest test/strstest
        #elif  [[ ${{ matrix.compiler }} == "powerpc64le-gcc" ]]; then
        #  make test/crctest test/emutest test/playtest test/strstest ${{ env.compile_env }}
        #  sed -e 's/exec "/exec qemu-ppc -L \/usr\/local\/powerpc64le -L \/usr\/powerpc64le-linux-gnu "/' -i test/crctest test/emutest test/playtest test/strstest
        #fi

    - name: Prepare MinGW runtime DLLs
      if: ${{ matrix.compiler == 'mingw-w64' }}
      run: |
        mkdir -p test/.libs
        LIBGCC_DLL=$(find /usr/lib/gcc/x86_64-w64-mingw32 -name libgcc_s_seh-1.dll | head -n1)
        LIBSTDCXX_DLL=$(find /usr/lib/gcc/x86_64-w64-mingw32 -name libstdc++-6.dll | head -n1)
        test -n "$LIBGCC_DLL" || { echo "libgcc_s_seh-1.dll not found" >&2; exit 1; }
        test -n "$LIBSTDCXX_DLL" || { echo "libstdc++-6.dll not found" >&2; exit 1; }
        cp "$LIBGCC_DLL" test/.libs/
        cp "$LIBSTDCXX_DLL" test/.libs/
        if [ -f /usr/x86_64-w64-mingw32/lib/libwinpthread-1.dll ]; then
          cp /usr/x86_64-w64-mingw32/lib/libwinpthread-1.dll test/.libs/
        else
          LIBWINPTHREAD_DLL=$(find /usr -name libwinpthread-1.dll | grep x86_64-w64-mingw32 | head -n1)
          test -n "$LIBWINPTHREAD_DLL" || { echo "libwinpthread-1.dll not found" >&2; exit 1; }
          cp "$LIBWINPTHREAD_DLL" test/.libs/
        fi
        if [ -d src/.libs ]; then cp src/.libs/*.dll test/.libs/ 2>/dev/null || true; fi
        if [ -n "$(find /usr/local /usr -name 'libbinio-1.dll' -print -quit 2>/dev/null)" ]; then
          cp "$(find /usr/local /usr -name 'libbinio-1.dll' -print -quit 2>/dev/null)" test/.libs/
        fi
        ls -1 test/.libs/*.dll 2>/dev/null || true

    - name: Prepare test results
      # qemu currently does not work with powerpc64-gcc, so skip that single instance
      if: ${{ (runner.os == 'Linux' || runner.os == 'macOS') && (matrix.compiler != 'powerpc64-gcc') }}
      run: |
        if [[ ${{ matrix.compiler }} = djgpp* ]]; then
          export LOG_COMPILER="dosemu"
          export AM_LOG_FLAGS="-dumb $f"
        fi
        make -j1 check ${{ env.compile_env }}
