name: CI

on:
  push:
    branches-ignore:
      - 'master'
      - 'ci/**'
      - '!ci/gha**'
  pull_request:
    branches:
      - 'master'

jobs:
  formatting:
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v2
      with:
        fetch-depth: 2
    - name: Install pcre2grep
      run: sudo apt-get update && sudo apt-get install -y pcre2-utils
    # Check for trailing whitespace
    - name: Trailing whitespace
      run: find simde/ -name '*.c' -o -name '*.h' -exec grep -nP '\s+$' {} + && exit 1 || exit 0
    # We use spaces, not tabs.  I don't want to start a holy war here;
    # I don't actually have a strong preference between the two, but I
    # do have a strong preference for consistency, so don't @ me.
    - name: Tabs
      run: find simde/ -name '*.c' -o -name '*.h' -exec grep -nP '\t' {} + && exit 1 || exit 0
    # s/8/16/ will result in this if the input is x86.
    - name: Bad substitutions
      run: git grep -i 'x''1''6''6' && exit 1 || exit 0
    - name: Incorrect assertions in test/
      run: grep -PR '(?<=[^a-zA-Z0-9_])simde_assert_u?int(8|16|32|64)(?>[^a-zA-Z0-9_])' test/ && exit 1 || exit 0
    # Check to make sure no source files have the executable bit set
    - name: Executable sources
      run: find \( -name '*.c' -o -name '*.h' \) -executable | grep -q '.' && exit 1 || exit 0
    # Make sure neon.h includes all the NEON headers.
    - name: Missing NEON includes
      run: for f in simde/arm/neon/*.h; do grep -q "include \"neon/$(basename "$f")\"" simde/arm/neon.h || (echo "Missing $f" && exit 1); done
    # Make sure we can find the expected header guards.  It's easy to miss this when doing C&P
    - name: Header guards
      run: for file in $(find simde/*/ -name '*.h'); do grep -q "$(echo "$file" | tr '[:lower:]' '[:upper:]' | tr '[:punct:]' '_')" "$file" || (echo "Missing or incorrect header guard in $file" && exit 1); done
    # There should be an empty line at the end of every file
    - name: Newline at EOF
      run: for file in $(find simde -name '*.h'); do if [ ! -z "$(tail -c 1 "$file")" ]; then echo "No newline at end of $file" && exit 1; fi; done
    # Don't #ifndef ; use !defined(...) instead.  ifndef leads to annoying inconsistencies
    - name: ifndef
      run: for file in $(find simde -name '*.h'); do grep -qP '^ *# *ifndef ' "${file}" && exit 1 || exit 0; done
    # List of headers we want Meson to install
    - name: Meson install headers
      run: for file in $(find simde -name '*.h'); do grep -qF "$(basename "${file}" .h)" meson.build || (echo "${file} missing from top-level meson.build" && exit 1); done
    # Make sure we don't accidentally use `vector ...` instead of SIMDE_POWER_ALTIVEC_VECTOR(...)
    - name: AltiVec raw vector keyword
      run: find simde/ -name '*.c' -o -name '*.h' -exec grep -nP 'vector( +)((bool|signed|unsigned) +)?(double|float|long long|long|int|short|char)' {} + && exit 1 || exit 0
    # Check indentation of preprocessor directives.
    - name: Preprocessor directive indentation
      run: find simde/*/ -name 'avx*.h' -exec pcre2grep -M '{\n#' {} + && exit 1 || exit 0

  # Running the tests in SDE is pretty slow, so we put these early
  # in the file so hopefully they start sooner.

  SDE:
    runs-on: ubuntu-latest
    strategy:
      matrix:
        arch: ["icelake-server"]
    env:
      CC: clang
      CXX: clang++
      CFLAGS: -march=icelake-server -Wall -Wextra -Werror
      CXXFLAGS: -march=icelake-server -Wall -Wextra -Werror
    steps:
    - uses: actions/checkout@v2
      with:
        submodules: recursive
    - name: CPU Information
      run: cat /proc/cpuinfo
    - name: Install APT Dependencies
      run: sudo add-apt-repository 'ppa:ubuntu-toolchain-r/test' && sudo apt-get update && sudo apt-get install -y ninja-build ninja-build python3-pip python3-setuptools python3-wheel parallel gcovr
    - name: Install pip Dependencies
      run: pip3 install meson
    - name: Download SDE
      run: ./test/download-sde.sh ~/sde
    - name: Configure
      run: ~/.local/bin/meson setup build -Db_coverage=true
    - name: Build
      run: ninja -C build -v
    - name: Test
      run: |
        find build/test/ -type f -executable -exec parallel ~/sde/sde64 -- ::: {} \;
    - name: Coverage Report
      run: ninja -C build -v coverage-xml
    - name: CodeCov.io
      uses: codecov/codecov-action@v1
      with:
        file: ./build/meson-logs/coverage.xml

  sleef-SDE:
    runs-on: ubuntu-20.04
    strategy:
      matrix:
        arch: ["icelake-server"]
    env:
      CC: clang
      CXX: clang++
      CFLAGS: -march=icelake-server -Wall -Wextra -Werror
      CXXFLAGS: -march=icelake-server -Wall -Wextra -Werror
    steps:
    - uses: actions/checkout@v2
      with:
        submodules: recursive
    - name: CPU Information
      run: cat /proc/cpuinfo
    - name: Install APT Dependencies
      run: sudo add-apt-repository 'ppa:ubuntu-toolchain-r/test' && sudo apt-get update && sudo apt-get install -y ninja-build ninja-build python3-pip python3-setuptools python3-wheel parallel gcovr libsleef-dev
    - name: Install pip Dependencies
      run: pip3 install meson
    - name: Download SDE
      run: ./test/download-sde.sh ~/sde
    - name: Configure
      run: ~/.local/bin/meson setup build -Dsleef=enabled -Db_coverage=true
    - name: Build
      run: ninja -C build -v
    - name: Test
      run: |
        find build/test/ -type f -executable -exec parallel ~/sde/sde64 -- ::: {} \;
    - name: Coverage Report
      run: ninja -C build -v coverage-xml
    - name: CodeCov.io
      uses: codecov/codecov-action@v1
      with:
        file: ./build/meson-logs/coverage.xml

  x86:
    runs-on: ubuntu-latest
    strategy:
      matrix:
        isax: ["", "-msse3", "-mssse3", "-msse4.1", "-msse4.2", "-mavx", "-mfma", "-mavx2", "-march=native"]
    env:
      CFLAGS: -Wall -Wextra -Werror ${{ matrix.isax }}
      CXXFLAGS: -Wall -Wextra -Werror ${{ matrix.isax }}
    steps:
    - uses: actions/checkout@v2
      with:
        submodules: recursive
    - name: CPU Information
      run: cat /proc/cpuinfo
    - name: Install APT Dependencies
      run: sudo add-apt-repository 'ppa:ubuntu-toolchain-r/test' && sudo apt-get update && sudo apt-get install -y ninja-build ninja-build python3-pip python3-setuptools python3-wheel parallel gcovr
    - name: Install pip Dependencies
      run: pip3 install meson
    - name: Configure
      run: ~/.local/bin/meson setup build -Db_coverage=true
    - name: Build
      run: ninja -C build -v
    - name: Test
      run: ninja -C build -v test
    - name: Coverage Report
      run: ninja -C build -v coverage-xml
    - name: CodeCov.io
      uses: codecov/codecov-action@v1
      with:
        file: ./build/meson-logs/coverage.xml

  avx512:
    runs-on: ubuntu-latest
    strategy:
      matrix:
        isax: ["-mavx512f", "-mavx512bw", "-mavx512cd", "-mavx512dq", "-mavx512vl", "-mavx512bw -mavx512vl", "-mavx512vl -mavx512dq"]
    env:
      CFLAGS: -Wall -Wextra -Werror ${{ matrix.isax }}
      CXXFLAGS: -Wall -Wextra -Werror ${{ matrix.isax }}
    steps:
    - uses: actions/checkout@v2
      with:
        submodules: recursive
    - name: CPU Information
      run: cat /proc/cpuinfo
    - name: Install APT Dependencies
      run: sudo add-apt-repository 'ppa:ubuntu-toolchain-r/test' && sudo apt-get update && sudo apt-get install -y ninja-build ninja-build python3-pip python3-setuptools python3-wheel parallel gcovr
    - name: Install pip Dependencies
      run: pip3 install meson
    - name: Configure
      run: ~/.local/bin/meson setup build -Db_coverage=true
    - name: Build
      run: ninja -C build -v
    # We can't actually run the tests without AVX-512. GitHub Actions doesn't
    # currently support it, and SDE is too slow.
    # - name: Test
    #   run: ninja -C build -v test
    # - name: Coverage Report
    #   run: ninja -C build -v coverage-xml
    # - name: CodeCov.io
    #   uses: codecov/codecov-action@v1
    #   with:
    #     file: ./build/meson-logs/coverage.xml

  emscripten:
    runs-on: ubuntu-latest
    env:
      CFLAGS: -Weverything -Werror -O3 -msimd128
      CXXFLAGS: -Weverything -Werror -O3 -msimd128
    steps:
    - uses: actions/checkout@v2
      with:
        submodules: recursive
    - name: CPU Information
      run: cat /proc/cpuinfo
    - name: Install APT Dependencies
      run: sudo add-apt-repository ppa:ubuntu-toolchain-r/test && sudo apt-get update && sudo apt-get -yq install ninja-build
    - name: Install emscripten
      run: |
        git clone https://github.com/emscripten-core/emsdk.git
        cd emsdk
        ./emsdk update-tags
        ./emsdk install tot
        ./emsdk activate tot
        source emsdk_env.sh
    - name: Install v8
      run: sudo npm install jsvu -g && jsvu --os=linux64 --engines=v8
    - name: Configure
      run: mkdir test/build && cd test/build && ../../emsdk/upstream/emscripten/emcmake cmake -G Ninja ..
    - name: Build
      run: ninja -C test/build -v
    - name: Test
      run: cd test/build && ~/.jsvu/v8 --experimental-wasm-simd run-tests.js

  native-aliases:
    runs-on: ubuntu-latest
    env:
      CC: gcc-10
      CXX: g++-10
      CFLAGS: -DSIMDE_ENABLE_NATIVE_ALIASES -DSIMDE_NATIVE_ALIASES_TESTING -march=native -Wall -Wextra -Werror
      CXXFLAGS: -DSIMDE_ENABLE_NATIVE_ALIASES -DSIMDE_NATIVE_ALIASES_TESTING -march=native -Wall -Wextra -Werror
    steps:
    - uses: actions/checkout@v2
      with:
        submodules: recursive
    - name: CPU Information
      run: cat /proc/cpuinfo
    - name: Install APT Dependencies
      run: sudo add-apt-repository ppa:ubuntu-toolchain-r/test && sudo apt-get update && sudo apt-get -yq install libxml2-utils ninja-build python3-pip python3-setuptools python3-wheel gcc-10 g++-10 parallel gcovr
    - name: Install pip Dependencies
      run: pip3 install meson
    - name: Convert
      run: ./test/native-aliases.sh
    - name: Configure
      run: ~/.local/bin/meson setup build -Db_coverage=true
    - name: Build
      run: ninja -C build -v
    - name: Test
      run: ninja -C build -v test
    - name: Coverage Report
      run: ninja -C build -v coverage-xml
    - name: CodeCov.io
      uses: codecov/codecov-action@v1
      with:
        file: ./build/meson-logs/coverage.xml

  sleef:
    runs-on: ubuntu-20.04
    env:
      CFLAGS: -march=native -Wall -Wextra -Werror
      CXXFLAGS: -march=native -Wall -Wextra -Werror
    steps:
    - uses: actions/checkout@v2
      with:
        submodules: recursive
    - name: CPU Information
      run: cat /proc/cpuinfo
    - name: Install APT Dependencies
      run: sudo add-apt-repository 'ppa:ubuntu-toolchain-r/test' && sudo apt-get update && sudo apt-get install -y ninja-build ninja-build python3-pip python3-setuptools python3-wheel parallel gcovr libsleef-dev
    - name: Install pip Dependencies
      run: pip3 install meson
    - name: Configure
      run: ~/.local/bin/meson setup build -Dsleef=enabled -Db_coverage=true
    - name: Build
      run: ninja -C build -v
    - name: Test
      run: ninja -C build -v test
    - name: Coverage Report
      run: ninja -C build -v coverage-xml
    - name: CodeCov.io
      uses: codecov/codecov-action@v1
      with:
        file: ./build/meson-logs/coverage.xml

  xenial-gcc:
    runs-on: ubuntu-16.04
    strategy:
      matrix:
        version: ["4.7", "4.8", "4.9", "5"]
    env:
      CC: gcc-${{ matrix.version }}
      CXX: g++-${{ matrix.version }}
      CFLAGS: -mavx2 -Wall -Wextra -Werror
      CXXFLAGS: -mavx2 -Wall -Wextra -Werror
    steps:
    - uses: actions/checkout@v2
      with:
        submodules: recursive
    - name: CPU Information
      run: cat /proc/cpuinfo
    - name: Install APT Dependencies
      run: sudo add-apt-repository ppa:ubuntu-toolchain-r/test && sudo apt-get update && sudo apt-get -yq install ninja-build parallel "${CC}" "${CXX}"
    - name: Configure
      run: mkdir test/build && cd test/build && cmake -G Ninja ..
    - name: Build
      run: ninja -C test/build -v
    - name: Test
      run: ninja -C test/build -v test

  xenial-clang:
    runs-on: ubuntu-16.04
    strategy:
      matrix:
        version: ["3.5", "3.9", "6.0"]
    env:
      CC: clang-${{ matrix.version }}
      CXX: clang++-${{ matrix.version }}
      CFLAGS: -mavx2 -Wall -Wextra -Werror
      CXXFLAGS: -mavx2 -Wall -Wextra -Werror
    steps:
    - uses: actions/checkout@v2
      with:
        submodules: recursive
    - name: CPU Information
      run: cat /proc/cpuinfo
    - name: Install APT Dependencies
      run: sudo add-apt-repository ppa:ubuntu-toolchain-r/test && sudo apt-get update && sudo apt-get -yq install ninja-build parallel clang-${{ matrix.version }}
    - name: Configure
      run: mkdir test/build && cd test/build && cmake -G Ninja ..
    - name: Build
      run: ninja -C test/build -v
    - name: Test
      run: ninja -C test/build -v test

  macos:
    runs-on: macos-latest
    strategy:
      matrix:
        # https://www.jessesquires.com/blog/2020/01/06/selecting-an-xcode-version-on-github-ci/
        # https://github.com/actions/virtual-environments/blob/master/images/macos/macos-10.15-Readme.md#xcode
        xcode: ["11.3.1", "11.7", "12.3"]
    env:
      DEVELOPER_DIR:  /Applications/Xcode_${{ matrix.xcode }}.app
    steps:
    - uses: actions/checkout@v2
      with:
        submodules: recursive
    - name: System Information
      run: system_profiler
    - name: Compiler version
      run: cc --version
    - name: Install Homebrew Dependencies
      run: brew install meson ninja gcovr
    - name: Configure
      run: meson setup build -Db_coverage=true
    - name: Build
      run: ninja -C build -v
    - name: Coverage Report
      run: ninja -C build -v coverage-xml
    - name: CodeCov.io
      uses: codecov/codecov-action@v1
      with:
        file: ./build/meson-logs/coverage.xml

  icc:
    runs-on: ubuntu-latest
    env:
      CC: /home/runner/.local/bin/icc
      CXX: /home/runner/.local/bin/icpc
      CFLAGS: -Werror -wd13200 -wd13203 -wd16219 -Wall -Werror -march=native
      CXXFLAGS: -wd13200 -wd13203 -wd16219 -Wall -Werror -march=native
    steps:
    - uses: actions/checkout@v2
    - name: CPU Information
      run: cat /proc/cpuinfo
    - name: Install APT Dependencies
      run: sudo apt-get install -y ninja-build ninja-build python3-pip python3-setuptools python3-wheel
    - name: Install ICC
      run: |
        curl -s https://apt.repos.intel.com/intel-gpg-keys/GPG-PUB-KEY-INTEL-SW-PRODUCTS-2023.PUB | sudo apt-key add -
        sudo add-apt-repository 'deb https://apt.repos.intel.com/oneapi all main'
        sudo apt-get update
        sudo apt-get install -y intel-oneapi-compiler-dpcpp-cpp-and-cpp-classic ninja-build ninja-build python3-pip python3-setuptools python3-wheel
        mkdir -p ~/.local/bin/ || true
        for exe in icc icpc; do
          printf '#!/bin/bash\nARGS="$@"\nsource /opt/intel/oneapi/compiler/latest/env/vars.sh >/dev/null\n%s ${ARGS}\n' "${exe}" > ~/.local/bin/"${exe}"
          chmod 0755 ~/.local/bin/"${exe}";
        done
    - name: Install pip Dependencies
      run: pip3 install meson
    - name: Configure
      run: ~/.local/bin/meson setup build
    - name: Build
      run: ninja -C build -v
    - name: Test
      run: ninja -C build -v test
