# For details, see README.md in this directory.

###############################################################
# C compilers
#
# - gcc
# - clang
#
# Known Issue
# - All test cases which described as 'fail' must be fixed and replaced with 'true'.
#   - gcc-11 (x32, x86) : "../lib/lz4hc.c:148: LZ4HC_countBack: Assertion `(size_t)(match - mMin) < (1U<<31)' failed."
#   - all clangs (x32, x86) : "../lib/lz4hc.c:282: int LZ4HC_InsertAndGetWiderMatch(...): Assertion `matchPtr >= lowPrefixPtr' failed."
#
name: lz4 CI
on: [push, pull_request]
permissions:
  contents: read

jobs:
  lz4-c-compilers:
    name: CC=${{ matrix.cc }}, ${{ matrix.os }}
    strategy:
      fail-fast: false  # 'false' means Don't stop matrix workflows even if some matrix failed.
      matrix:
        include: [
          # You can access the following values via ${{ matrix.??? }}
          #
          #   pkgs         : apt-get package names.  It can include multiple package names which are delimited by space.
          #   cc           : C compiler executable.
          #   cxx          : C++ compiler executable for `make ctocpptest`.
          #   x32          : Set 'true' if compiler supports x32.  Otherwise, set 'false'.
          #                  Set 'fail' if it supports x32 but fails for now.  'fail' cases must be removed.
          #   x86          : Set 'true' if compiler supports x86 (-m32).  Otherwise, set 'false'.
          #                  Set 'fail' if it supports x86 but fails for now.  'fail' cases must be removed.
          #   cxxtest      : Set 'true' if it can be compiled as C++ code.  Otherwise, set 'false'.
          #   freestanding : Set 'true' if it can be compiled and execute freestanding code.  Otherwise, set 'false'.
          #                  Usually, it requires Linux, x86_64 and gcc/g++.
          #   os           : GitHub Actions YAML workflow label.  See https://github.com/actions/virtual-environments#available-environments

          # cc
          { pkgs: '',                                                   cc: cc,        cxx: c++,         x32: 'true', x86: 'true', cxxtest: 'true',  freestanding: 'true',  os: ubuntu-latest, },

          # gcc
          { pkgs: '',                                                   cc: gcc,       cxx: g++,         x32: 'true', x86: 'true', cxxtest: 'true',  freestanding: 'true',  os: ubuntu-latest, },
          { pkgs: 'gcc-12 g++-12 lib32gcc-12-dev libx32gcc-12-dev',     cc: gcc-12,    cxx: g++-12,      x32: 'true', x86: 'true', cxxtest: 'true',  freestanding: 'true',  os: ubuntu-22.04,  },
          { pkgs: 'gcc-11 g++-11 lib32gcc-11-dev libx32gcc-11-dev',     cc: gcc-11,    cxx: g++-11,      x32: 'true', x86: 'true', cxxtest: 'true',  freestanding: 'true',  os: ubuntu-22.04,  },
          { pkgs: 'gcc-10 g++-10 lib32gcc-10-dev libx32gcc-10-dev',     cc: gcc-10,    cxx: g++-10,      x32: 'true', x86: 'true', cxxtest: 'true',  freestanding: 'true',  os: ubuntu-22.04,  },
          { pkgs: 'gcc-9 g++-9 lib32gcc-9-dev libx32gcc-9-dev',         cc: gcc-9,     cxx: g++-9,       x32: 'true', x86: 'true', cxxtest: 'true',  freestanding: 'true',  os: ubuntu-22.04,  },
          { pkgs: 'gcc-8 g++-8 lib32gcc-8-dev libx32gcc-8-dev',         cc: gcc-8,     cxx: g++-8,       x32: 'true', x86: 'true', cxxtest: 'true',  freestanding: 'true',  os: ubuntu-20.04,  },
          { pkgs: 'gcc-7 g++-7 lib32gcc-7-dev libx32gcc-7-dev',         cc: gcc-7,     cxx: g++-7,       x32: 'true', x86: 'true', cxxtest: 'true',  freestanding: 'true',  os: ubuntu-20.04,  },
          { pkgs: 'gcc-6 g++-6 lib32gcc-6-dev libx32gcc-6-dev',         cc: gcc-6,     cxx: g++-6,       x32: 'true', x86: 'true', cxxtest: 'true',  freestanding: 'true',  os: ubuntu-18.04,  },
          { pkgs: 'gcc-5 g++-5 lib32gcc-5-dev libx32gcc-5-dev',         cc: gcc-5,     cxx: g++-5,       x32: 'true', x86: 'true', cxxtest: 'true',  freestanding: 'true',  os: ubuntu-18.04,  },
          { pkgs: 'gcc-4.8 g++-4.8 lib32gcc-4.8-dev libx32gcc-4.8-dev', cc: gcc-4.8,   cxx: g++-4.8,     x32: 'true', x86: 'true', cxxtest: 'true',  freestanding: 'true',  os: ubuntu-18.04,  },

          # clang
          { pkgs: 'lib32gcc-11-dev libx32gcc-11-dev',                   cc: clang,     cxx: clang++,     x32: 'true', x86: 'true', cxxtest: 'true',  freestanding: 'false', os: ubuntu-latest, },
          { pkgs: 'clang-14  lib32gcc-11-dev libx32gcc-11-dev',         cc: clang-14,  cxx: clang++-14,  x32: 'true', x86: 'true', cxxtest: 'true',  freestanding: 'false', os: ubuntu-22.04,  },
          { pkgs: 'clang-13  lib32gcc-11-dev libx32gcc-11-dev',         cc: clang-13,  cxx: clang++-13,  x32: 'true', x86: 'true', cxxtest: 'true',  freestanding: 'false', os: ubuntu-22.04,  },
          { pkgs: 'clang-12  lib32gcc-11-dev libx32gcc-11-dev',         cc: clang-12,  cxx: clang++-12,  x32: 'true', x86: 'true', cxxtest: 'true',  freestanding: 'false', os: ubuntu-22.04,  },
          { pkgs: 'clang-11  lib32gcc-11-dev libx32gcc-11-dev',         cc: clang-11,  cxx: clang++-11,  x32: 'true', x86: 'true', cxxtest: 'true',  freestanding: 'false', os: ubuntu-22.04,  },
          { pkgs: 'clang-10  lib32gcc-11-dev libx32gcc-11-dev',         cc: clang-10,  cxx: clang++-10,  x32: 'true', x86: 'true', cxxtest: 'true',  freestanding: 'false', os: ubuntu-20.04,  },
          { pkgs: 'clang-9   lib32gcc-11-dev libx32gcc-11-dev',         cc: clang-9,   cxx: clang++-9,   x32: 'true', x86: 'true', cxxtest: 'true',  freestanding: 'false', os: ubuntu-20.04,  },
          { pkgs: 'clang-8   lib32gcc-11-dev libx32gcc-11-dev',         cc: clang-8,   cxx: clang++-8,   x32: 'true', x86: 'true', cxxtest: 'true',  freestanding: 'false', os: ubuntu-20.04,  },
          { pkgs: 'clang-7   lib32gcc-7-dev  libx32gcc-7-dev',          cc: clang-7,   cxx: clang++-7,   x32: 'true', x86: 'true', cxxtest: 'true',  freestanding: 'false', os: ubuntu-20.04,  },
          { pkgs: 'clang-6.0 lib32gcc-11-dev libx32gcc-11-dev',         cc: clang-6.0, cxx: clang++-6.0, x32: 'true', x86: 'true', cxxtest: 'true',  freestanding: 'false', os: ubuntu-20.04,  },
          { pkgs: 'clang-5.0 lib32gcc-11-dev libx32gcc-11-dev',         cc: clang-5.0, cxx: clang++-5.0, x32: 'true', x86: 'true', cxxtest: 'true',  freestanding: 'false', os: ubuntu-18.04,  },
          { pkgs: 'clang-4.0 lib32gcc-11-dev libx32gcc-11-dev',         cc: clang-4.0, cxx: clang++-4.0, x32: 'true', x86: 'true', cxxtest: 'true',  freestanding: 'false', os: ubuntu-18.04,  },
          { pkgs: 'clang-3.9',                                          cc: clang-3.9, cxx: clang++-3.9, x32: 'fail', x86: 'fail', cxxtest: 'false', freestanding: 'false', os: ubuntu-18.04,  },
        ]

    runs-on: ${{ matrix.os }}
    env:                        # Set environment variables
      # We globally set CC and CXX to improve compatibility with .travis.yml
      CC: ${{ matrix.cc }}
      CXX: ${{ matrix.cxx }}
      FIXME__LZ4_CI_IGNORE : ' echo Error.  But we ignore it for now.'
    steps:
    - uses: actions/checkout@v2 # https://github.com/actions/checkout

    - name: apt-get install
      run: |
        sudo apt-get update
        sudo apt-get install gcc-multilib
        sudo apt-get install ${{ matrix.pkgs }}

    - name: Environment info
      run: |
        echo && type $CC && which $CC && $CC --version
        echo && type $CXX && which $CXX && $CXX --version

    - name: make
      if: always()
      run: make V=1

    - name: install test
      if: always()
      run: make clean; make V=1 -C tests test-install

    - name: make all
      if: always()
      run: make V=1 clean all

    - name: make c_standards (C90)
      if: always()
      run: make V=1 clean c_standards_c90

    - name: make c_standards (C11)
      if: always()
      run: make V=1 clean c_standards_c11

    - name: make c-to-c++
      if: always()
      run: make V=1 clean ctocpptest

    - name: make cxxtest
      if: ${{ matrix.cxxtest == 'true' }}
      run: make V=1 clean cxxtest

    - name: make test-freestanding
      if: ${{ matrix.freestanding == 'true' }}
      run: make V=1 clean test-freestanding

    - name: make -C programs default
      if: always()
      run: make V=1 -C programs clean default

    - name: make -C programs default -D_FORTIFY_SOURCE=2
      if: always()
      run: CFLAGS='-fPIC' LDFLAGS='-pie -fPIE -D_FORTIFY_SOURCE=2' make V=1 -C programs clean default

    - name: make -C tests test-lz4
      if: always()
      run: make clean; MOREFLAGS='-Werror' make -j V=1 -C tests test-lz4

    - name: make clangtest (clang only)
      if: ${{ startsWith( matrix.cc , 'clang' ) }}
      run: make V=1 clean clangtest

    - name: make -C tests test MOREFLAGS='-mx32'
      if: ${{ matrix.x32 == 'true' }}
      run: make clean; LDFLAGS='-Wl,--verbose' MOREFLAGS='-mx32' make -j V=1 -C tests test

    - name: make -C tests test-lz4c32
      if: ${{ matrix.x86 == 'true' }}
      run: LDFLAGS='-Wl,--verbose' MOREFLAGS='-Werror' make V=1 -C tests clean test-lz4c32


    ###############################################################
    #                                                             #
    #      Remove this block when we stabilize the tests.         #
    #                                                             #

    - name: make -C tests test MOREFLAGS='-mx32' || echo Ignore failure for now.
      if: ${{ matrix.x32 == 'fail' }}
      run: make clean; LDFLAGS='-Wl,--verbose' MOREFLAGS='-mx32' make -j V=1 -C tests test || $FIXME__LZ4_CI_IGNORE

    - name: make -C tests test-lz4c32 || echo Ignore failure for now.
      if: ${{ matrix.x86 == 'fail' }}
      run: make clean; LDFLAGS='-Wl,--verbose' MOREFLAGS='-Werror' make V=1 -C tests test-lz4c32 || $FIXME__LZ4_CI_IGNORE

    #                                                             #
    ###############################################################



###############################################################
# LZ4 self tests
#
# - Benchmark
# - Fuzzer
# - LZ4 Frame
# - LZ4 versions
# - Custom LZ4_DISTANCE_MAX
#
  lz4-benchmark:
    name: Benchmark
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v2 # https://github.com/actions/checkout

    - name: apt-get install
      run: |
        sudo apt-get update
        sudo apt-get install gcc-multilib

    - name: benchmark (-C tests test-lz4)
      run: make -j V=1 -C tests test-lz4

    - name: benchmark (-C tests test-lz4c)
      run: make -j V=1 -C tests test-lz4c

    - name: benchmark (-C tests test-lz4c32)
      run: make V=1 -C tests test-lz4c32

    - name: benchmark (-C tests test-fullbench)
      run: make V=1 -C tests test-fullbench

    - name: benchmark (-C tests test-fullbench32)
      run: make V=1 -C tests test-fullbench32


  lz4-fuzzer:
    name: Fuzzer test
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v2 # https://github.com/actions/checkout

    - name: apt-get install
      run: |
        sudo apt-get update
        sudo apt-get install gcc-multilib

    - name: setup
      run: sudo sysctl -w vm.mmap_min_addr=4096

    - name: fuzzer
      run: make V=1 -C tests test-fuzzer

    - name: fuzzer32
      run: make V=1 -C tests test-fuzzer32


  lz4-standard-makefile-variables:
    name: LZ4 Makefile - support for standard variables
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v2 # https://github.com/actions/checkout

    - name: make standard_variables
      run: make V=1 standard_variables


  lz4-versions:
    name: LZ4 versions test
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v2 # https://github.com/actions/checkout

    - name: apt-get install
      run: |
        sudo apt-get update
        sudo apt-get install gcc-multilib

    - name: make -C tests versionsTest
      run: make V=1 -C tests versionsTest


  lz4-abi:
    name: LZ4 inter-versions ABI test
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v2 # https://github.com/actions/checkout

    - name: apt-get install
      run: |
        sudo apt-get update
        sudo apt-get install gcc-multilib

    - name: make -C tests abiTests
      run: make V=1 -C tests abiTests


  lz4-frame:
    name: LZ4 frame test
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v2 # https://github.com/actions/checkout

    - name: apt-get install
      run: |
        sudo apt-get update
        sudo apt-get install gcc-multilib

    - name: LZ4 frame test
      run: make V=1 -C tests test-frametest

    - name: LZ4 frame test (32-bit)
      run: make V=1 -C tests test-frametest32

  lz4-memory-usage:
    name: test different values of LZ4_MEMORY_USAGE
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v2 # https://github.com/actions/checkout
    - name: LZ4_MEMORY_USAGE
      run: make V=1 -C tests test-compile-with-lz4-memory-usage

  # Custom LZ4_DISTANCE_MAX ; lz4-wlib (CLI linked to dynamic library); LZ4_USER_MEMORY_FUNCTIONS
  lz4-custom-distance:
    name: Custom LZ4_DISTANCE_MAX
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v2 # https://github.com/actions/checkout
    - name: custom LZ4_DISTANCE_MAX; test LZ4_USER_MEMORY_FUNCTIONS
      run: |
        MOREFLAGS='-DLZ4_DISTANCE_MAX=8000' make V=1 check
        make V=1 clean
        make V=1 -C programs lz4-wlib
        make V=1 clean
        make V=1 -C tests fullbench-wmalloc  # test LZ4_USER_MEMORY_FUNCTIONS
        make V=1 clean
        CC="c++ -Wno-deprecated" make V=1 -C tests fullbench-wmalloc  # stricter function signature check

  # test block device compression #1086
  lz4cli-block-device:
    name: Test lz4 compression on a block device
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v2 # https://github.com/actions/checkout
    - name: create a block device, compress it with lz4 # alternative : blindly use /dev/loop0, seems to always exist
      run: |
        make lz4
        dd if=/dev/zero of=full0.img bs=2M count=1
        BLOCK_DEVICE=$(sudo losetup --show -fP full0.img)
        sudo chmod 666 $BLOCK_DEVICE
        ./lz4 -v $BLOCK_DEVICE -c > /dev/null
        sudo losetup -d $BLOCK_DEVICE
        rm full0.img


###############################################################
# Check tools
#
# - cppcheck
# - scan-build
# - valgrind
# - ubsan
# - asan
# - unicode-lint
# - build examples
#
  lz4-cppcheck:
    name: make cppcheck
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v2 # https://github.com/actions/checkout
    - name: apt-get install
      run: |
        sudo apt-get update
        sudo apt-get install cppcheck

    - name: Environment info
      run: echo && type cppcheck && which cppcheck && cppcheck --version

    - name: cppcheck
      # This test script ignores the exit code of cppcheck.
      # See known issues in README.md.
      run: make V=1 clean cppcheck || echo There are some cppcheck reports but we ignore it.


  lz4-scan-build:
    name: make staticAnalyze
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v2 # https://github.com/actions/checkout
    - name: apt-get install
      run: |
        sudo apt-get update
        sudo apt-get install clang-tools

    - name: Environment info
      run: |
        echo && type gcc && which gcc && gcc --version
        echo && type clang && which clang && clang --version
        echo && type scan-build && which scan-build               # scan-build doesn't have any --version equivalent option
        echo && type make && which make && make -v
        echo && cat /proc/cpuinfo || echo /proc/cpuinfo is not present

    - name: make staticAnalyze
      run: make V=1 clean staticAnalyze


  lz4-valgrind:
    name: valgrind
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v2 # https://github.com/actions/checkout
    - name: apt-get install
      run: |
        sudo apt-get update
        sudo apt-get install valgrind

    - name: Environment info
      run: |
        echo && type cc && which cc && cc --version
        echo && type valgrind && which valgrind && valgrind --version

    - name: valgrind
      run: make V=1 -C tests test-mem


  lz4-ubsan-x64:
    name: Linux x64 ubsan
    runs-on: ubuntu-latest
    env:                        # Set environment variables
      FIXME__LZ4_CI_IGNORE : ' echo Error.  But we ignore it for now.'
    steps:
    - uses: actions/checkout@v2 # https://github.com/actions/checkout

    - name: ubsan
      #########################################################
      # For now, we ignore the exit code of `make usan`.
      # See "Known issues / lz4-ubsan-x64" in README.md
      # When we'll resolve this issue, remove "|| $FIXME__LZ4_CI_IGNORE"
      #########################################################
      run: make V=1 clean usan MOREFLAGS='-Wcomma -Werror' || $FIXME__LZ4_CI_IGNORE


  lz4-ubsan-x86:
    name: Linux x86 ubsan
    runs-on: ubuntu-latest
    env:                        # Set environment variables
      FIXME__LZ4_CI_IGNORE : ' echo Error.  But we ignore it for now.'
    steps:
    - uses: actions/checkout@v2 # https://github.com/actions/checkout

    - name: apt-get install
      run: |
        sudo apt-get update
        sudo apt-get install gcc-multilib
        sudo apt-get install lib32gcc-11-dev

    - name: ubsan32
      #########################################################
      # For now, we ignore the exit code of `make usan32`.
      # See "Known issues / lz4-ubsaan-x86" in README.md.
      # When we'll resolve this issue, remove "|| $FIXME__LZ4_CI_IGNORE"
      #########################################################
      run: CC=clang make V=1 clean usan32 MOREFLAGS='-Wcomma -Werror' || $FIXME__LZ4_CI_IGNORE


  lz4-asan-x64:
    name: Linux x64 ASAN
    runs-on: ubuntu-latest
    env:                        # Set environment variables
      FIXME__LZ4_CI_IGNORE : ' echo Error.  But we ignore it for now.'
    steps:
    - uses: actions/checkout@v2 # https://github.com/actions/checkout

    - name: setup
      run: sudo sysctl -w vm.mmap_min_addr=4096

    - name: frametest
      run: CC=clang MOREFLAGS=-fsanitize=address make V=1 -C tests clean test-frametest

    - name: fuzzer
      run: CC=clang MOREFLAGS=-fsanitize=address make V=1 -C tests clean test-fuzzer

  unicode-lint:
    name: lint unicode in ./lib/, ./tests/ and ./programs/
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v2 # https://github.com/actions/checkout
    - name: unicode lint
      run: bash ./tests/unicode_lint.sh

  lz4-examples:
    name: make examples
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v2 # https://github.com/actions/checkout
    - name: apt-get install
      run: |
        sudo apt-get update

    - name: Environment info
      run: |
        echo && type cc && which cc && cc --version
        echo && type c++ && which c++ && c++ --version

    - name: examples
      run: make V=1 clean examples

    - name: examples (compile as C++ code)
      run: make V=1 -C examples clean cxxtest

  # lasts ~20mn
  oss-fuzz:
    runs-on: ubuntu-latest
    strategy:
      fail-fast: false
      matrix:
        sanitizer: [address, undefined, memory]
    steps:
    - name: Build Fuzzers (${{ matrix.sanitizer }})
      id: build
      uses: google/oss-fuzz/infra/cifuzz/actions/build_fuzzers@master
      with:
        oss-fuzz-project-name: 'lz4'
        dry-run: false
        sanitizer: ${{ matrix.sanitizer }}
    - name: Run Fuzzers (${{ matrix.sanitizer }})
      uses: google/oss-fuzz/infra/cifuzz/actions/run_fuzzers@master
      with:
        oss-fuzz-project-name: 'lz4'
        fuzz-seconds: 600
        dry-run: false
        sanitizer: ${{ matrix.sanitizer }}
    - name: Upload Crash
      uses: actions/upload-artifact@v1
      if: failure() && steps.build.outcome == 'success'
      with:
        name: ${{ matrix.sanitizer }}-artifacts
        path: ./out/artifacts



###############################################################
# Platforms
#
# - QEMU (ARM, ARM64, PPC, PPC64LE, S390X)
# - macOS
#

  # QEMU
  # All tests use QEMU (static) and gcc cross compiler.
  #
  # note:
  #   We don't employ completely matrix method which provides `MOREFLAGS`
  #   etc in the matrix.  Because some platform may need its special
  #   compiler options and test.
  #   For example, xxHash already has tests for scalar and SIMD version of
  #   it.  But compiler options are quite different between platforms.
  #
  #   So, please keep them simple and independent.
  #
  lz4-qemu-platforms:
    name: QEMU ${{ matrix.type }}
    strategy:
      fail-fast: false  # 'false' means Don't stop matrix workflows even if some matrix instance failed.
      matrix:
        include: [
          # You can access the following values via ${{ matrix.??? }}
          #   type : Architecture type for `if:` statement.
          #   pkgs : apt-get package names.  You can include multiple packages which are delimited by space.
          #   xcc  : gcc cross C compiler executable.
          #   xemu : QEMU static emulator executable.
          #   os   : GitHub Actions YAML workflow label.  See https://github.com/actions/virtual-environments#available-environments

          { type: ARM,      pkgs: 'qemu-system-arm   gcc-arm-linux-gnueabi',     xcc: arm-linux-gnueabi-gcc,     xemu: qemu-arm-static,     os: ubuntu-latest, },
          { type: ARM64,    pkgs: 'qemu-system-arm   gcc-aarch64-linux-gnu',     xcc: aarch64-linux-gnu-gcc,     xemu: qemu-aarch64-static, os: ubuntu-latest, },
          { type: PPC,      pkgs: 'qemu-system-ppc   gcc-powerpc-linux-gnu',     xcc: powerpc-linux-gnu-gcc,     xemu: qemu-ppc-static,     os: ubuntu-latest, },
          { type: PPC64LE,  pkgs: 'qemu-system-ppc   gcc-powerpc64le-linux-gnu', xcc: powerpc64le-linux-gnu-gcc, xemu: qemu-ppc64le-static, os: ubuntu-latest, },
          { type: S390X,    pkgs: 'qemu-system-s390x gcc-s390x-linux-gnu',       xcc: s390x-linux-gnu-gcc,       xemu: qemu-s390x-static,   os: ubuntu-latest, },
        ]

    runs-on: ${{ matrix.os }}
    env:                        # Set environment variables
      XCC: ${{ matrix.xcc }}
      XEMU: ${{ matrix.xemu }}
    steps:
    - uses: actions/checkout@v2 # https://github.com/actions/checkout

    - name: apt-get install
      run: |
        sudo apt-get update
        sudo apt-get install gcc-multilib
        sudo apt-get install qemu-utils qemu-user-static
        sudo apt-get install ${{ matrix.pkgs }}

    - name: Environment info
      run: |
        echo && type $XCC && which $XCC && $XCC --version
        echo && $XCC -v                       # Show built-in specs
        echo && type $XEMU && which $XEMU && $XEMU --version

    - name: ARM64
      if: ${{ matrix.type == 'ARM64' }}
      run: make V=1 platformTest CC=$XCC QEMU_SYS=$XEMU

    - name: ARM
      if: ${{ matrix.type == 'ARM' }}
      run: make V=1 platformTest CC=$XCC QEMU_SYS=$XEMU

    - name: PPC
      if: ${{ matrix.type == 'PPC' }}
      run: make V=1 platformTest CC=$XCC QEMU_SYS=$XEMU

    - name: PPC64LE
      if: ${{ matrix.type == 'PPC64LE' }}
      run: make V=1 platformTest CC=$XCC QEMU_SYS=$XEMU MOREFLAGS=-m64

    - name: S390X
      if: ${{ matrix.type == 'S390X' }}
      run: make V=1 platformTest CC=$XCC QEMU_SYS=$XEMU


  # macOS
  lz4-platform-macos-latest:
    name: macOS
    runs-on: macos-latest
    steps:
    - uses: actions/checkout@v2

    - name: Environment info
      run: |
        echo && type cc && which cc && cc --version
        echo && type make && which make && make -v
        echo && sysctl -a | grep machdep.cpu   # cpuinfo

    - name: make default
      run: CFLAGS="-Werror" make V=1 clean default

    - name: make test
      run: make clean; make -j V=1 test MOREFLAGS='-Werror -Wconversion -Wno-sign-conversion'

    - name: Ensure `make test` doesn't depend on the status of the console
      # see issue #990 for detailed explanations
      run: make -j test > /dev/null


###############################################################
# Build systems
#
# - make
# - cmake
# - meson
#

  # make
  lz4-build-make:
    name: make
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v2 # https://github.com/actions/checkout

    - name: Environment info
      run: |
        echo && type cc && which cc && cc --version
        echo && type make && which make && make -v

    - name: make
      run: make V=1


  lz4-build-make-travis-install:
    name: make travis-install
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v2 # https://github.com/actions/checkout

    - name: travis-install
      run: make V=1 clean travis-install

    - name: travis-install result
      run: |
        echo && echo Installed files
        ( cd ~/install_test_dir; find .; )


  # cmake
  lz4-build-cmake:
    name: cmake
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v2 # https://github.com/actions/checkout

    - name: Environment info
      run: |
        echo && type cmake && which cmake && cmake --version
        echo && type make && which make && make -v

    - name: cmake
      run: |
        cd build/cmake
        mkdir build
        cd build
        cmake ..
        CFLAGS=-Werror make VERBOSE=1


  # Invoke cmake via Makefile
  lz4-build-make-cmake:
    name: make cmake
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v2 # https://github.com/actions/checkout
    - name: make cmake
      # V=1 for lz4 Makefile, VERBOSE=1 for cmake Makefile.
      run: make V=1 VERBOSE=1 clean cmake


  # Meson
  lz4-build-meson:
    name: Meson + Ninja
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v2 # https://github.com/actions/checkout
    - uses: actions/setup-python@v2 # https://github.com/actions/setup-python
      with:
        python-version: '3.x'

    - name: Install
      run: |
        sudo apt-get update
        sudo apt-get install tree ninja-build
        python -m pip install --upgrade pip
        pip3 install --user meson

    - name: Environment info
      run: |
        echo && type clang && which clang && clang --version
        echo && type python && which python && python --version
        echo && type meson && which meson && meson --version

    - name: meson
      # 'run: >' replaces all newlines in the following block with spaces
      run: >
        meson setup
        --buildtype=debug
        -Db_lundef=false
        -Dauto_features=enabled
        -Dprograms=true
        -Dcontrib=true
        -Dtests=true
        -Dexamples=true
        contrib/meson build

    - name: staging
      run: |
        cd build
        DESTDIR=./staging ninja install
        tree ./staging



############################################################
# Check git tag for LZ4 releases
#
  lz4-check-tag:
    name: git version tag checking for release
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v2
    - name: make -C tests checkTag
      if: startsWith(github.ref, 'refs/tags/v')   # If git tag name starts with 'v'
      run: |
        echo "tag=${GITHUB_REF#refs/*/}"
        make -C tests checkTag
        tests/checkTag ${GITHUB_REF#refs/*/}



############################################################
# Gather CI environment information.
#
  lz4-env-info:
    name: GH-Actions Virtual Env Info (${{ matrix.os }})
    strategy:
      matrix:
        include: [
          { os: ubuntu-latest,  }, # https://github.com/actions/virtual-environments/
          { os: ubuntu-22.04,   }, # https://github.com/actions/virtual-environments/blob/main/images/linux/Ubuntu2204-Readme.md
          { os: ubuntu-20.04,   }, # https://github.com/actions/virtual-environments/blob/main/images/linux/Ubuntu2004-Readme.md
          { os: ubuntu-18.04,   }, # https://github.com/actions/virtual-environments/blob/main/images/linux/Ubuntu1804-Readme.md
        ]

    runs-on: ${{ matrix.os }}
    steps:
    - uses: actions/checkout@v2

    - name: init
      run: |
        sudo apt-get update

    - name: cc --version
      run: echo && type cc && which cc && cc --version

    - name: gcc --version
      run: echo && type gcc && which gcc && gcc --version

    - name: clang --version
      run: echo && type clang && which clang && clang --version

    - name: make -v
      run: echo && type make && which make && make -v

    - name: g++ --version
      run: echo && type g++ && which g++ && g++ --version

    - name: git --version
      run: echo && type git && which git && git --version

    - name: gcc packages (apt-cache)
      run: apt-cache search gcc | grep "^gcc-[0-9\.]* " | sort

    - name: lib32gcc packages for i386 (apt-cache)
      run: apt-cache search lib32gcc | grep "^lib32gcc-" | sort

    - name: libx32gcc packages for x32 (apt-cache)
      run: apt-cache search libx32gcc | grep "^libx32gcc-" | sort

    - name: gcc multilib packages (apt-cache)
      run: apt-cache search multilib | grep "gcc-" | sort

    - name: clang packages (apt-cache)
      run: apt-cache search clang | grep "^clang-[0-9\.]* " | sort

    - name: QEMU packages (apt-cache)
      run: apt-cache search qemu | grep "^qemu-system-.*QEMU full system" | sort
