# Copyright (C) 2019 Intel Corporation.  All rights reserved.
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception

name: compilation on android, ubuntu-20.04, ubuntu-22.04

on:
  # will be triggered on PR events
  pull_request:
    paths-ignore:
      - "assembly-script/**"
      - "ci/**"
      - "doc/**"
      - "test-tools/**"
      - ".github/workflows/compilation_on_android_ubuntu.yml"
  # will be triggered on push events
  push:
    paths-ignore:
      - "assembly-script/**"
      - "ci/**"
      - "doc/**"
      - "test-tools/**"
      - ".github/workflows/compilation_on_android_ubuntu.yml"
  # allow to be triggered manually
  workflow_dispatch:

# Cancel any in-flight jobs for the same PR/branch so there's only one active
# at a time
concurrency:
  group: ${{ github.workflow }}-${{ github.ref }}
  cancel-in-progress: true

env:
  # For BUILD
  AOT_BUILD_OPTIONS: "-DWAMR_BUILD_AOT=1 -DWAMR_BUILD_FAST_INTERP=0 -DWAMR_BUILD_INTERP=0 -DWAMR_BUILD_JIT=0 -DWAMR_BUILD_LAZY_JIT=0"
  CLASSIC_INTERP_BUILD_OPTIONS: "-DWAMR_BUILD_AOT=0 -DWAMR_BUILD_FAST_INTERP=0 -DWAMR_BUILD_INTERP=1 -DWAMR_BUILD_JIT=0 -DWAMR_BUILD_LAZY_JIT=0"
  FAST_INTERP_BUILD_OPTIONS: "-DWAMR_BUILD_AOT=0 -DWAMR_BUILD_FAST_INTERP=1 -DWAMR_BUILD_INTERP=1 -DWAMR_BUILD_JIT=0 -DWAMR_BUILD_LAZY_JIT=0"
  LAZY_JIT_BUILD_OPTIONS: "-DWAMR_BUILD_AOT=1 -DWAMR_BUILD_FAST_INTERP=0 -DWAMR_BUILD_INTERP=0 -DWAMR_BUILD_JIT=1 -DWAMR_BUILD_LAZY_JIT=1"
  MC_JIT_BUILD_OPTIONS: "-DWAMR_BUILD_AOT=1 -DWAMR_BUILD_FAST_INTERP=0 -DWAMR_BUILD_INTERP=0 -DWAMR_BUILD_JIT=1 -DWAMR_BUILD_LAZY_JIT=0"
  # LLVM
  LLVM_CACHE_SUFFIX: "build-llvm_libraries_ex"
  # For Spec Test
  DEFAULT_TEST_OPTIONS: "-s spec -P"
  MULTI_MODULES_TEST_OPTIONS: "-s spec -M -P"
  SIMD_TEST_OPTIONS: "-s spec -S -P"
  THREADS_TEST_OPTIONS: "-s spec -p -P"
  X86_32_TARGET_TEST_OPTIONS: "-m x86_32 -P"

jobs:
  # Cancel any in-flight jobs for the same PR/branch so there's only one active
  # at a time
  cancel_previous:
    runs-on: ${{ matrix.os }}
    strategy:
      matrix:
        os: [ubuntu-20.04, ubuntu-22.04]
    steps:
      - name: Cancel Workflow Action
        uses: styfle/cancel-workflow-action@0.9.1
        with:
          access_token: ${{ github.token }}

  # set different traffic lights based on the current repo and the running OS.
  # according to light colors, the workflow will run different jobs
  # it is used to separate between the public repo and the private repo
  check_repo:
    needs: cancel_previous
    runs-on: ${{ matrix.os }}
    strategy:
      matrix:
        os: [ubuntu-20.04, ubuntu-22.04]
    outputs:
      traffic_light_on_ubuntu_2004: ${{ steps.do_check_on_ubuntu_2004.outputs.light }}
      traffic_light_on_ubuntu_2204: ${{ steps.do_check_on_ubuntu_2204.outputs.light }}
    steps:
      - name: do_check_on_ubuntu_2004
        id: do_check_on_ubuntu_2004
        if: ${{ matrix.os == 'ubuntu-20.04' }}
        run: |
          if [[ ${{ github.repository }} == */wasm-micro-runtime ]]; then
            echo "::set-output name=light::green"
          else
            echo "::set-output name=light::red"
          fi

      - name: do_check_on_ubuntu_2204
        id: do_check_on_ubuntu_2204
        if: ${{ matrix.os == 'ubuntu-22.04' }}
        run: |
          if [[ ${{ github.repository }} == */wasm-micro-runtime ]]; then
            echo "::set-output name=light::green"
          else
            echo "::set-output name=light::green"
          fi

  build_llvm_libraries:
    needs: check_repo
    runs-on: ${{ matrix.os }}
    strategy:
      matrix:
        os: [ubuntu-20.04, ubuntu-22.04]
        include:
          - os: ubuntu-20.04
            light: ${{ needs.check_repo.outputs.traffic_light_on_ubuntu_2004 }}
          - os: ubuntu-22.04
            light: ${{ needs.check_repo.outputs.traffic_light_on_ubuntu_2204 }}
    steps:
      - name: light status
        run: echo "matrix.os=${{ matrix.os }}, light=${{ matrix.light }}"

      - name: checkout
        if: ${{ matrix.light == 'green' }}
        uses: actions/checkout@v3

      - name: Cache LLVM libraries
        id: cache_llvm
        if: ${{ matrix.light == 'green' }}
        uses: actions/cache@v3
        with:
          path: |
            ./core/deps/llvm/build/bin
            ./core/deps/llvm/build/include
            ./core/deps/llvm/build/lib
            ./core/deps/llvm/build/libexec
            ./core/deps/llvm/build/share
          key: ${{ matrix.os }}-${{ env.LLVM_CACHE_SUFFIX }}

      - name: Build llvm and clang from source
        id: build_llvm
        if: ${{ matrix.light == 'green' && steps.cache_llvm.outputs.cache-hit != 'true' }}
        run: /usr/bin/env python3 ./build_llvm.py --arch X86 WebAssembly --project clang lldb
        working-directory: build-scripts

  build_wamrc:
    needs: [build_llvm_libraries, check_repo]
    runs-on: ${{ matrix.os }}
    strategy:
      matrix:
        os: [ubuntu-20.04, ubuntu-22.04]
        include:
          - os: ubuntu-20.04
            light: ${{ needs.check_repo.outputs.traffic_light_on_ubuntu_2004 }}
          - os: ubuntu-22.04
            light: ${{ needs.check_repo.outputs.traffic_light_on_ubuntu_2204 }}
    steps:
      - name: light status
        run: echo "matrix.os=${{ matrix.os }}, light=${{ matrix.light }}"

      - name: checkout
        if: ${{ matrix.light == 'green' }}
        uses: actions/checkout@v3

      - name: Get LLVM libraries
        id: cache_llvm
        if: ${{ matrix.light == 'green' }}
        uses: actions/cache@v3
        with:
          path: |
            ./core/deps/llvm/build/bin
            ./core/deps/llvm/build/include
            ./core/deps/llvm/build/lib
            ./core/deps/llvm/build/libexec
            ./core/deps/llvm/build/share
          key: ${{ matrix.os }}-${{ env.LLVM_CACHE_SUFFIX }}

      - name: Quit if cache miss
        if: ${{ matrix.light == 'green' && steps.cache_llvm.outputs.cache-hit != 'true' }}
        run: echo "::error::can not get prebuilt llvm libraries" && exit 1

      - name: Build wamrc
        if: ${{ matrix.light == 'green' }}
        run: |
          mkdir build && cd build
          cmake ..
          cmake --build . --config Release --parallel 4
        working-directory: wamr-compiler

  build_iwasm:
    needs: [build_llvm_libraries, check_repo]
    runs-on: ${{ matrix.os }}
    strategy:
      matrix:
        make_options_run_mode: [
            # Running mode
            $AOT_BUILD_OPTIONS,
            $CLASSIC_INTERP_BUILD_OPTIONS,
            $FAST_INTERP_BUILD_OPTIONS,
            $LAZY_JIT_BUILD_OPTIONS,
            $MC_JIT_BUILD_OPTIONS,
          ]
        make_options_feature: [
            # Features
            "-DWAMR_BUILD_CUSTOM_NAME_SECTION=1",
            "-DWAMR_BUILD_DEBUG_AOT=1",
            "-DWAMR_BUILD_DEBUG_INTERP=1",
            "-DWAMR_BUILD_DUMP_CALL_STACK=1",
            "-DWAMR_BUILD_LIB_PTHREAD=1",
            "-DWAMR_BUILD_LOAD_CUSTOM_SECTION=1",
            "-DWAMR_BUILD_MINI_LOADER=1",
            "-DWAMR_BUILD_MEMORY_PROFILING=1",
            "-DWAMR_BUILD_MULTI_MODULE=1",
            "-DWAMR_BUILD_PERF_PROFILING=1",
            "-DWAMR_BUILD_REF_TYPES=1",
            "-DWAMR_BUILD_SIMD=1",
            "-DWAMR_BUILD_TAIL_CALL=1",
            "-DWAMR_DISABLE_HW_BOUND_CHECK=1",
          ]
        os: [ubuntu-20.04, ubuntu-22.04]
        platform: [android, linux]
        exclude:
          # uncompatiable feature and platform
          # uncompatiable mode and feature
          # MULTI_MODULE only on INTERP mode
          - make_options_run_mode: $LAZY_JIT_BUILD_OPTIONS
            make_options_feature: "-DWAMR_BUILD_MULTI_MODULE=1"
          - make_options_run_mode: $AOT_BUILD_OPTIONS
            make_options_feature: "-DWAMR_BUILD_MULTI_MODULE=1"
          - make_options_run_mode: $MC_JIT_BUILD_OPTIONS
            make_options_feature: "-DWAMR_BUILD_MULTI_MODULE=1"
          # SIMD only on JIT/AOT mode
          - make_options_run_mode: $CLASSIC_INTERP_BUILD_OPTIONS
            make_options_feature: "-DWAMR_BUILD_SIMD=1"
          - make_options_run_mode: $FAST_INTERP_BUILD_OPTIONS
            make_options_feature: "-DWAMR_BUILD_SIMD=1"
          # DEBUG_INTERP only on CLASSIC INTERP mode
          - make_options_run_mode: $AOT_BUILD_OPTIONS
            make_options_feature: "-DWAMR_BUILD_DEBUG_INTERP=1"
          - make_options_run_mode: $LAZY_JIT_BUILD_OPTIONS
            make_options_feature: "-DWAMR_BUILD_DEBUG_INTERP=1"
          - make_options_run_mode: $MC_JIT_BUILD_OPTIONS
            make_options_feature: "-DWAMR_BUILD_DEBUG_INTERP=1"
          - make_options_run_mode: $FAST_INTERP_BUILD_OPTIONS
            make_options_feature: "-DWAMR_BUILD_DEBUG_INTERP=1"
          # DEBUG_AOT only on JIT/AOT mode
          - make_options_run_mode: $CLASSIC_INTERP_BUILD_OPTIONS
            make_options_feature: "-DWAMR_BUILD_DEBUG_AOT=1"
          - make_options_run_mode: $FAST_INTERP_BUILD_OPTIONS
            make_options_feature: "-DWAMR_BUILD_DEBUG_AOT=1"
          # TODO: DEBUG_AOT on JIT
          - make_options_run_mode: $LAZY_JIT_BUILD_OPTIONS
            make_options_feature: "-DWAMR_BUILD_DEBUG_AOT=1"
          - make_options_run_mode: $MC_JIT_BUILD_OPTIONS
            make_options_feature: "-DWAMR_BUILD_DEBUG_AOT=1"
          # MINI_LOADER only on INTERP mode
          - make_options_run_mode: $AOT_BUILD_OPTIONS
            make_options_feature: "-DWAMR_BUILD_MINI_LOADER=1"
          - make_options_run_mode: $LAZY_JIT_BUILD_OPTIONS
            make_options_feature: "-DWAMR_BUILD_MINI_LOADER=1"
          - make_options_run_mode: $MC_JIT_BUILD_OPTIONS
            make_options_feature: "-DWAMR_BUILD_MINI_LOADER=1"
        include:
          - os: ubuntu-20.04
            light: ${{ needs.check_repo.outputs.traffic_light_on_ubuntu_2004 }}
          - os: ubuntu-22.04
            light: ${{ needs.check_repo.outputs.traffic_light_on_ubuntu_2204 }}
    steps:
      - name: light status
        run: echo "matrix.os=${{ matrix.os }}, light=${{ matrix.light }}"

      - name: checkout
        if: ${{ matrix.light == 'green' }}
        uses: actions/checkout@v3

      # only download llvm cache when needed
      - name: Get LLVM libraries
        id: cache_llvm
        if: (matrix.light == 'green') && (endsWith(matrix.make_options_run_mode, '_JIT_BUILD_OPTIONS'))
        uses: actions/cache@v3
        with:
          path: |
            ./core/deps/llvm/build/bin
            ./core/deps/llvm/build/include
            ./core/deps/llvm/build/lib
            ./core/deps/llvm/build/libexec
            ./core/deps/llvm/build/share
          key: ${{ matrix.os }}-${{ env.LLVM_CACHE_SUFFIX }}

      - name: Quit if cache miss
        if: (matrix.light == 'green') && (endsWith(matrix.make_options_run_mode, '_JIT_BUILD_OPTIONS')) && (steps.cache_llvm.outputs.cache-hit != 'true')
        run: echo "::error::can not get prebuilt llvm libraries" && exit 1

      - name: Build iwasm
        if: ${{ matrix.light == 'green' }}
        run: |
          mkdir build && cd build
          cmake .. ${{ matrix.make_options_run_mode }} ${{ matrix.make_options_feature }}
          cmake --build . --config Release --parallel 4
        working-directory: product-mini/platforms/${{ matrix.platform }}

  build_samples_wasm_c_api:
    needs: [build_iwasm, build_llvm_libraries, build_wamrc, check_repo]
    runs-on: ${{ matrix.os }}
    strategy:
      matrix:
        make_options: [
            # Running mode
            $CLASSIC_INTERP_BUILD_OPTIONS,
            $FAST_INTERP_BUILD_OPTIONS,
            $LAZY_JIT_BUILD_OPTIONS,
            $MC_JIT_BUILD_OPTIONS,
            $AOT_BUILD_OPTIONS,
          ]
        os: [ubuntu-20.04, ubuntu-22.04]
        include:
          - os: ubuntu-20.04
            light: ${{ needs.check_repo.outputs.traffic_light_on_ubuntu_2004 }}
            wasi_sdk_release: https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-12/wasi-sdk-12.0-linux.tar.gz
            wabt_release: https://github.com/WebAssembly/wabt/releases/download/1.0.24/wabt-1.0.24-ubuntu.tar.gz
          - os: ubuntu-22.04
            light: ${{ needs.check_repo.outputs.traffic_light_on_ubuntu_2204 }}
            wasi_sdk_release: https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-12/wasi-sdk-12.0-linux.tar.gz
            wabt_release: https://github.com/WebAssembly/wabt/releases/download/1.0.24/wabt-1.0.24-ubuntu.tar.gz
    steps:
      - name: light status
        run: echo "matrix.os=${{ matrix.os }}, light=${{ matrix.light }}"

      - name: checkout
        if: ${{ matrix.light == 'green' }}
        uses: actions/checkout@v3

      - name: Get LLVM libraries
        id: cache_llvm
        if: (matrix.light == 'green') && (!endsWith(matrix.make_options, '_INTERP_BUILD_OPTIONS'))
        uses: actions/cache@v3
        with:
          path: |
            ./core/deps/llvm/build/bin
            ./core/deps/llvm/build/include
            ./core/deps/llvm/build/lib
            ./core/deps/llvm/build/libexec
            ./core/deps/llvm/build/share
          key: ${{ matrix.os }}-${{ env.LLVM_CACHE_SUFFIX }}

      - name: Quit if cache miss
        if: (matrix.light == 'green') && (!endsWith(matrix.make_options, '_INTERP_BUILD_OPTIONS')) && (steps.cache_llvm.outputs.cache-hit != 'true')
        run: echo "::error::can not get prebuilt llvm libraries" && exit 1

      - name: download and install wabt
        if: ${{ matrix.light == 'green' }}
        run: |
          cd /opt
          sudo wget ${{ matrix.wabt_release }}
          sudo tar -xzf wabt-1.0.24-*.tar.gz
          sudo mv wabt-1.0.24 wabt

      - name: Build wamrc
        if: (matrix.light == 'green') && (!endsWith(matrix.make_options, '_INTERP_BUILD_OPTIONS'))
        run: |
          mkdir build && cd build
          cmake ..
          cmake --build . --config Release --parallel 4
        working-directory: wamr-compiler

      - name: Build Sample [wasm-c-api]
        if: ${{ matrix.light == 'green' }}
        run: |
          mkdir build && cd build
          cmake .. ${{ matrix.make_options }}
          cmake --build . --config Release --parallel 4
          ./callback
          ./callback_chain
          ./empty_imports
          ./global
          ./hello
          ./hostref
          ./memory
          ./reflect
          ./table
          ./trap
        working-directory: samples/wasm-c-api

  build_samples_others:
    needs: [build_iwasm, check_repo]
    runs-on: ${{ matrix.os }}
    strategy:
      matrix:
        include:
          - os: ubuntu-20.04
            light: ${{ needs.check_repo.outputs.traffic_light_on_ubuntu_2004 }}
            wasi_sdk_release: https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-12/wasi-sdk-12.0-linux.tar.gz
            wabt_release: https://github.com/WebAssembly/wabt/releases/download/1.0.24/wabt-1.0.24-ubuntu.tar.gz
          - os: ubuntu-22.04
            light: ${{ needs.check_repo.outputs.traffic_light_on_ubuntu_2204 }}
            wasi_sdk_release: https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-12/wasi-sdk-12.0-linux.tar.gz
            wabt_release: https://github.com/WebAssembly/wabt/releases/download/1.0.24/wabt-1.0.24-ubuntu.tar.gz
    steps:
      - name: light status
        run: echo "matrix.os=${{ matrix.os }}, light=${{ matrix.light }}"

      - name: checkout
        if: ${{ matrix.light == 'green' }}
        uses: actions/checkout@v3

      - name: download and install wasi-sdk
        if: ${{ matrix.light == 'green' }}
        run: |
          cd /opt
          sudo wget ${{ matrix.wasi_sdk_release }}
          sudo tar -xzf wasi-sdk-12.0-*.tar.gz
          sudo mv wasi-sdk-12.0 wasi-sdk

      - name: download and install wabt
        if: ${{ matrix.light == 'green' }}
        run: |
          cd /opt
          sudo wget ${{ matrix.wabt_release }}
          sudo tar -xzf wabt-1.0.24-*.tar.gz
          sudo mv wabt-1.0.24 wabt

      - name: Build Sample [basic]
        if: ${{ matrix.light == 'green' }}
        run: |
          cd samples/basic
          ./build.sh
          ./run.sh

      - name: Build Sample [multi-thread]
        if: ${{ matrix.light == 'green' }}
        run: |
          cd samples/multi-thread
          mkdir build && cd build
          cmake ..
          cmake --build . --config Release --parallel 4
          ./iwasm wasm-apps/test.wasm

      - name: Build Sample [multi-module]
        if: ${{ matrix.light == 'green' }}
        run: |
          cd samples/multi-module
          mkdir build && cd build
          cmake ..
          cmake --build . --config Release --parallel 4
          ./multi_module

      - name: Build Sample [spawn-thread]
        if: ${{ matrix.light == 'green' }}
        run: |
          cd samples/spawn-thread
          mkdir build && cd build
          cmake ..
          cmake --build . --config Release --parallel 4
          ./spawn_thread

      - name: Build Sample [ref-types]
        if: ${{ matrix.light == 'green' }}
        run: |
          cd samples/ref-types
          mkdir build && cd build
          cmake ..
          cmake --build . --config Release --parallel 4
          ./hello

  spec_test_default:
    needs: [build_iwasm, build_llvm_libraries, build_wamrc, check_repo]
    runs-on: ubuntu-20.04
    strategy:
      matrix:
        test_option: [$DEFAULT_TEST_OPTIONS]
    steps:
      - name: checkout
        uses: actions/checkout@v3

      - name: Get LLVM libraries
        id: cache_llvm
        uses: actions/cache@v3
        with:
          path: |
            ./core/deps/llvm/build/bin
            ./core/deps/llvm/build/include
            ./core/deps/llvm/build/lib
            ./core/deps/llvm/build/libexec
            ./core/deps/llvm/build/share
          key: ubuntu-20.04-${{ env.LLVM_CACHE_SUFFIX }}

      - name: Quit if cache miss
        if: steps.cache_llvm.outputs.cache-hit != 'true'
        run: echo "::error::can not get prebuilt llvm libraries" && exit 1

      - name: install Ninja
        run: sudo apt install -y ninja-build

      - name: run spec tests
        run: ./test_wamr.sh ${{ matrix.test_option }}
        working-directory: ./tests/wamr-test-suites

  spec_test_extra:
    if: ${{ endsWith(github.repository, 'wasm-micro-runtime') }}
    needs: [build_iwasm, build_llvm_libraries, build_wamrc, check_repo]
    runs-on: ubuntu-20.04
    strategy:
      matrix:
        running_mode: ["classic-interp", "fast-interp", "jit", "aot"]
        test_option:
          [
            $MULTI_MODULES_TEST_OPTIONS,
            $SIMD_TEST_OPTIONS,
            $THREADS_TEST_OPTIONS,
          ]
    steps:
      - name: checkout
        uses: actions/checkout@v3

      - name: Get LLVM libraries
        id: cache_llvm
        uses: actions/cache@v3
        with:
          path: |
            ./core/deps/llvm/build/bin
            ./core/deps/llvm/build/include
            ./core/deps/llvm/build/lib
            ./core/deps/llvm/build/libexec
            ./core/deps/llvm/build/share
          key: ubuntu-20.04-${{ env.LLVM_CACHE_SUFFIX }}

      - name: Quit if cache miss
        if: steps.cache_llvm.outputs.cache-hit != 'true'
        run: echo "::error::can not get prebuilt llvm libraries" && exit 1

      - name: install Ninja
        run: sudo apt install -y ninja-build

      - name: run spec tests
        run: ./test_wamr.sh ${{ matrix.test_option }} -t ${{ matrix.running_mode }}
        working-directory: ./tests/wamr-test-suites

  spec_test_x86_32:
    if: ${{ endsWith(github.repository, 'wasm-micro-runtime') }}
    needs: [build_iwasm, build_llvm_libraries, build_wamrc, check_repo]
    runs-on: ubuntu-20.04
    strategy:
      matrix:
        running_mode: ["classic-interp", "fast-interp", "jit", "aot"]
        test_option: [$DEFAULT_TEST_OPTIONS, $THREADS_TEST_OPTIONS]
    steps:
      - name: checkout
        uses: actions/checkout@v3

      - name: Get LLVM libraries
        id: cache_llvm
        uses: actions/cache@v3
        with:
          path: |
            ./core/deps/llvm/build/bin
            ./core/deps/llvm/build/include
            ./core/deps/llvm/build/lib
            ./core/deps/llvm/build/libexec
            ./core/deps/llvm/build/share
          key: ubuntu-20.04-${{ env.LLVM_CACHE_SUFFIX }}

      - name: Quit if cache miss
        if: steps.cache_llvm.outputs.cache-hit != 'true'
        run: echo "::error::can not get prebuilt llvm libraries" && exit 1

      - name: install Ninja and x32 support libraries
        run:
          # Add another apt repository as some packages cannot
          # be downloaded with the github default repository
          sudo curl -sSL https://packages.microsoft.com/keys/microsoft.asc | sudo tee /etc/apt/trusted.gpg.d/microsoft.asc &&
          sudo apt-add-repository https://packages.microsoft.com/ubuntu/20.04/prod &&
          sudo apt-get update &&
          sudo apt install -y g++-multilib lib32gcc-9-dev ninja-build

      - name: run spec tests
        run: ./test_wamr.sh ${{ env.X86_32_TARGET_TEST_OPTIONS }} ${{ matrix.test_option }} -t ${{ matrix.running_mode }}
        working-directory: ./tests/wamr-test-suites
