name: Full Flutter CI

on:
  workflow_dispatch:
  pull_request:
  push:
    branches:
      - master
    tags:
      - '*'
    paths-ignore:
      - ".github/**"

env:
  LLVM_VERSION: "10.0"
  # Note: currently 3.0.5 does not support arm64 officially, we use latest stable version first.
  FLUTTER_VERSION: "3.0.5"
  # vcpkg version: 2022.05.10
  # for multiarch gcc compatibility
  VCPKG_COMMIT_ID: "14e7bb4ae24616ec54ff6b2f6ef4e8659434ea44"
  VERSION: "1.2.0"

jobs:
  build-for-windows:
    name: ${{ matrix.job.target }} (${{ matrix.job.os }})
    runs-on: ${{ matrix.job.os }}
    strategy:
      fail-fast: true
      matrix:
        job:
          # - { target: i686-pc-windows-msvc        , os: windows-2019                  }
          # - { target: x86_64-pc-windows-gnu       , os: windows-2019                  }
          - { target: x86_64-pc-windows-msvc, os: windows-2019 }
    steps:
      - name: Checkout source code
        uses: actions/checkout@v3

      - name: Install LLVM and Clang
        uses: KyleMayes/install-llvm-action@v1
        with:
          version: ${{ env.LLVM_VERSION }}

      - name: Install flutter
        uses: subosito/flutter-action@v2
        with:
          channel: "stable"
          flutter-version: ${{ env.FLUTTER_VERSION }}
          cache: true

      - name: Replace engine with rustdesk custom flutter engine
        run: |
          flutter doctor -v
          flutter precache --windows
          Invoke-WebRequest -Uri https://github.com/Kingtous/engine/releases/download/v3.0.5-rustdesk.2/windows-x64-flutter-release.zip -OutFile windows-x64-flutter-release.zip
          Expand-Archive windows-x64-flutter-release.zip -DestinationPath engine
          mv -Force engine/*  C:/hostedtoolcache/windows/flutter/stable-3.0.5-x64/bin/cache/artifacts/engine/windows-x64-release/

      - name: Install Rust toolchain
        uses: actions-rs/toolchain@v1
        with:
          toolchain: "1.62"
          target: ${{ matrix.job.target }}
          override: true
          components: rustfmt
          profile: minimal # minimal component installation (ie, no documentation)

      - uses: Swatinem/rust-cache@v2
        with:
          prefix-key: ${{ matrix.job.os }}

      - name: Install flutter rust bridge deps
        run: |
          dart pub global activate ffigen --version 5.0.1
          $exists = Test-Path ~/.cargo/bin/flutter_rust_bridge_codegen.exe
          Push-Location ..
          git clone https://github.com/SoLongAndThanksForAllThePizza/flutter_rust_bridge --depth=1
          Push-Location flutter_rust_bridge/frb_codegen ; cargo install --path . ; Pop-Location
          Pop-Location
          Push-Location flutter ; flutter pub get ; Pop-Location
          ~/.cargo/bin/flutter_rust_bridge_codegen --rust-input ./src/flutter_ffi.rs --dart-output ./flutter/lib/generated_bridge.dart

      - name: Restore from cache and install vcpkg
        uses: lukka/run-vcpkg@v7
        with:
          setupOnly: true
          vcpkgGitCommitId: ${{ env.VCPKG_COMMIT_ID }}

      - name: Install vcpkg dependencies
        run: |
          $VCPKG_ROOT/vcpkg install libvpx:x64-windows-static libyuv:x64-windows-static opus:x64-windows-static
        shell: bash

      - name: Build rustdesk
        run: python3 .\build.py --portable --hwcodec --flutter

  build-for-macOS:
    name: ${{ matrix.job.target }} (${{ matrix.job.os }}) [${{ matrix.job.extra-build-args }}]
    runs-on: ${{ matrix.job.os }}
    strategy:
      fail-fast: true
      matrix:
        job:
          - {
              target: x86_64-apple-darwin,
              os: macos-latest,
              extra-build-args: "",
            }
    steps:
      - name: Checkout source code
        uses: actions/checkout@v3

      - name: Install build runtime
        run: |
          brew install llvm create-dmg nasm yasm cmake gcc wget ninja

      - name: Install flutter
        uses: subosito/flutter-action@v2
        with:
          channel: "stable"
          flutter-version: ${{ env.FLUTTER_VERSION }}

      - name: Install Rust toolchain
        uses: actions-rs/toolchain@v1
        with:
          toolchain: stable
          target: ${{ matrix.job.target }}
          override: true
          profile: minimal # minimal component installation (ie, no documentation)

      - uses: Swatinem/rust-cache@v2
        with:
          prefix-key: ${{ matrix.job.os }}

      - name: Install flutter rust bridge deps
        shell: bash
        run: |
          dart pub global activate ffigen --version 5.0.1
          # flutter_rust_bridge
          pushd /tmp
            wget https://github.com/Kingtous/flutter_rust_bridge/releases/download/1.32.0-rustdesk/flutter_rust_bridge_codegen-x86_64-darwin.tgz
            tar -zxvf flutter_rust_bridge_codegen-x86_64-darwin.tgz
            mkdir -p ~/.cargo/bin
            mv flutter_rust_bridge_codegen ~/.cargo/bin; chmod +x ~/.cargo/bin/flutter_rust_bridge_codegen
          popd
          pushd flutter && flutter pub get && popd
          ~/.cargo/bin/flutter_rust_bridge_codegen --rust-input ./src/flutter_ffi.rs --dart-output ./flutter/lib/generated_bridge.dart

      - name: Restore from cache and install vcpkg
        uses: lukka/run-vcpkg@v7
        with:
          setupOnly: true
          vcpkgGitCommitId: ${{ env.VCPKG_COMMIT_ID }}

      - name: Install vcpkg dependencies
        run: |
          $VCPKG_ROOT/vcpkg install libvpx libyuv opus

      - name: Show version information (Rust, cargo, Clang)
        shell: bash
        run: |
          clang --version || true
          rustup -V
          rustup toolchain list
          rustup default
          cargo -V
          rustc -V

      - name: Build rustdesk
        run: |
          # --hwcodec not supported on macos yet
          ./build.py --flutter ${{ matrix.job.extra-build-args }}

  build-vcpkg-deps-linux:
    runs-on: ${{ matrix.job.os }}
    strategy:
      fail-fast: true
      matrix:
        job:
          # - { arch: armv7, os: ubuntu-20.04 }
          - { arch: x86_64, os: ubuntu-20.04 }
          - { arch: aarch64, os: ubuntu-20.04 }
    steps:
      - name: Create vcpkg artifacts folder
        run: mkdir -p /opt/artifacts

      - name: Cache Vcpkg
        id: cache-vcpkg
        uses: actions/cache@v3
        with:
          path: /opt/artifacts
          key: vcpkg-${{ matrix.job.arch }}

      - uses: Kingtous/run-on-arch-action@amd64-support
        name: Run vcpkg install on ${{ matrix.job.arch }}
        id: vcpkg
        with:
          arch: ${{ matrix.job.arch }}
          distro: ubuntu18.04
          githubToken: ${{ github.token }}
          setup: |
            ls -l "/opt/artifacts"
          dockerRunArgs: |
            --volume "/opt/artifacts:/artifacts"
          shell: /bin/bash
          install: |
            apt update -y
            case "${{ matrix.job.arch }}" in
              x86_64)
                # CMake 3.15+
                apt install -y gpg wget ca-certificates
                echo 'deb [signed-by=/usr/share/keyrings/kitware-archive-keyring.gpg] https://apt.kitware.com/ubuntu/ bionic main' | tee /etc/apt/sources.list.d/kitware.list >/dev/null
                wget -O - https://apt.kitware.com/keys/kitware-archive-latest.asc 2>/dev/null | gpg --dearmor - | tee /usr/share/keyrings/kitware-archive-keyring.gpg >/dev/null
                apt update -y
                apt install -y curl zip unzip tar git cmake g++ gcc build-essential pkg-config wget nasm yasm ninja-build libjpeg8-dev
                ;;
              aarch64|armv7)
                apt install -y curl zip unzip tar git cmake g++ gcc build-essential pkg-config wget nasm yasm ninja-build libjpeg8-dev automake libtool
            esac
            cmake --version
            gcc -v
          run: |
            # disable git safe.directory
            git config --global --add safe.directory "*"
            case "${{ matrix.job.arch }}" in
              x86_64)
                export VCPKG_FORCE_SYSTEM_BINARIES=1
                pushd /artifacts
                git clone https://github.com/microsoft/vcpkg.git || true
                pushd vcpkg
                git reset --hard ${{ env.VCPKG_COMMIT_ID }}
                ./bootstrap-vcpkg.sh
                ./vcpkg install libvpx libyuv opus
                ;;
              aarch64|armv7)
                pushd /artifacts
                # libyuv
                git clone https://chromium.googlesource.com/libyuv/libyuv || true
                pushd libyuv
                git pull
                mkdir -p build
                pushd build
                mkdir -p /artifacts/vcpkg/installed
                cmake .. -DCMAKE_INSTALL_PREFIX=/artifacts/vcpkg/installed
                make -j4 && make install
                popd
                popd
                # libopus, ubuntu 18.04 prebuilt is not be compiled with -fPIC
                wget -O opus.tar.gz http://archive.ubuntu.com/ubuntu/pool/main/o/opus/opus_1.1.2.orig.tar.gz
                tar -zxvf opus.tar.gz; ls -l
                pushd opus-1.1.2
                ./autogen.sh; ./configure --prefix=/artifacts/vcpkg/installed
                make -j4; make install
                ;;
            esac
      - name: Upload artifacts
        uses: actions/upload-artifact@master
        with:
          name: vcpkg-artifact-${{ matrix.job.arch }}
          path: |
            /opt/artifacts/vcpkg/installed

  generate-bridge-linux:
    name: generate bridge
    runs-on: ${{ matrix.job.os }}
    strategy:
      fail-fast: true
      matrix:
        job:
          - {
              target: x86_64-unknown-linux-gnu,
              os: ubuntu-18.04,
              extra-build-args: "",
            }
    steps:
      - name: Checkout source code
        uses: actions/checkout@v3

      - name: Install prerequisites
        run: |
          sudo apt update -y
          sudo apt install -y g++ gcc git curl wget nasm yasm libgtk-3-dev clang cmake libclang-dev ninja-build llvm-dev libclang-10-dev llvm-10-dev pkg-config

      - name: Install Rust toolchain
        uses: actions-rs/toolchain@v1
        with:
          toolchain: stable
          target: ${{ matrix.job.target }}
          override: true
          profile: minimal # minimal component installation (ie, no documentation)

      - uses: Swatinem/rust-cache@v2
        with:
          prefix-key: bridge-${{ matrix.job.os }}
          workspace: "/tmp/flutter_rust_bridge/frb_codegen"

      - name: Cache Bridge
        id: cache-bridge
        uses: actions/cache@v3
        with:
          path: /tmp/flutter_rust_bridge
          key: vcpkg-${{ matrix.job.arch }}

      - name: Install flutter
        uses: subosito/flutter-action@v2
        with:
          channel: "stable"
          flutter-version: ${{ env.FLUTTER_VERSION }}
          cache: true

      - name: Install ffigen
        run: |
          dart pub global activate ffigen --version 5.0.1

      - name: Install flutter rust bridge deps
        shell: bash
        run: |
          pushd /tmp && git clone https://github.com/SoLongAndThanksForAllThePizza/flutter_rust_bridge --depth=1 || true && popd
          pushd /tmp/flutter_rust_bridge/frb_codegen && cargo install --path . && popd
          pushd flutter && flutter pub get && popd

      - name: Run flutter rust bridge
        run: |
          ~/.cargo/bin/flutter_rust_bridge_codegen --rust-input ./src/flutter_ffi.rs --dart-output ./flutter/lib/generated_bridge.dart

      - name: Upload Artifact
        uses: actions/upload-artifact@master
        with:
          name: bridge-artifact
          path: |
            ./src/bridge_generated.rs
            ./flutter/lib/generated_bridge.dart 
            ./flutter/lib/generated_bridge.freezed.dart

  build-rustdesk-android-arm64:
    needs: [generate-bridge-linux]
    name: build rustdesk android apk ${{ matrix.job.target }} (${{ matrix.job.os }}) [${{ matrix.job.extra-build-features }}]
    runs-on: ${{ matrix.job.os }}
    strategy:
      fail-fast: true
      matrix:
        job:
          - {
              arch: x86_64,
              target: aarch64-linux-android,
              os: ubuntu-18.04,
              extra-build-features: "",
            }
          # - {
          #     arch: x86_64,
          #     target: armv7-linux-androideabi,
          #     os: ubuntu-18.04,
          #     extra-build-features: "",
          #   }
    steps:
      - name: Install dependencies
        run: |
          sudo apt update
          sudo apt-get -qq install -y  git curl wget nasm yasm libgtk-3-dev clang libxcb-randr0-dev libxdo-dev libxfixes-dev libxcb-shape0-dev libxcb-xfixes0-dev libasound2-dev libpulse-dev cmake libclang-dev ninja-build libappindicator3-dev libgstreamer1.0-dev libgstreamer-plugins-base1.0-dev libvdpau-dev libva-dev libclang-dev llvm-dev libclang-10-dev llvm-10-dev pkg-config tree g++ libc6-dev gcc-multilib g++-multilib openjdk-11-jdk-headless
      - name: Checkout source code
        uses: actions/checkout@v3
      - name: Install flutter
        uses: subosito/flutter-action@v2
        with:
          channel: "stable"
          flutter-version: ${{ env.FLUTTER_VERSION }}
      - uses: nttld/setup-ndk@v1
        id: setup-ndk
        with:
          ndk-version: r22b
          add-to-path: true

      - name: Download deps
        shell: bash
        run: |
          pushd /opt
          wget https://github.com/rustdesk/doc.rustdesk.com/releases/download/console/dep.tar.gz
          tar xzf dep.tar.gz

      - name: Restore bridge files
        uses: actions/download-artifact@master
        with:
          name: bridge-artifact
          path: ./

      - name: Install Rust toolchain
        uses: actions-rs/toolchain@v1
        with:
          toolchain: stable
          override: true
          profile: minimal # minimal component installation (ie, no documentation)

      - uses: Swatinem/rust-cache@v2
        with:
          prefix-key: rustdesk-lib-cache
          key: ${{ matrix.job.target }}-${{ matrix.job.extra-build-features }}

      - name: Disable rust bridge build
        run: |
          sed -i "s/gen_flutter_rust_bridge();/\/\//g" build.rs

      - name: Build rustdesk lib
        env:
          ANDROID_NDK_HOME: ${{ steps.setup-ndk.outputs.ndk-path }}
          ANDROID_NDK_ROOT: ${{ steps.setup-ndk.outputs.ndk-path }}
          VCPKG_ROOT: /opt/vcpkg
        run: |
          rustup target add ${{ matrix.job.target }} 
          cargo install cargo-ndk
          case ${{ matrix.job.target }} in
            aarch64-linux-android)
              ./flutter/ndk_arm64.sh
              mkdir -p ./flutter/android/app/src/main/jniLibs/arm64-v8a
              cp ./target/${{ matrix.job.target }}/release/liblibrustdesk.so ./flutter/android/app/src/main/jniLibs/arm64-v8a/librustdesk.so
            ;;
            armv7-linux-androideabi)
              ./flutter/ndk_arm.sh
              mkdir -p ./flutter/android/app/src/main/jniLibs/armeabi-v7a
              cp ./target/${{ matrix.job.target }}/release/liblibrustdesk.so ./flutter/android/app/src/main/jniLibs/armeabi-v7a/librustdesk.so
            ;;
          esac

      - name: Build rustdesk
        shell: bash
        env:
          JAVA_HOME: /usr/lib/jvm/java-11-openjdk-amd64
        run: |
          export PATH=/usr/lib/jvm/java-11-openjdk-amd64/bin:$PATH
          # download so
          pushd flutter
            wget -O so.tar.gz https://github.com/rustdesk/doc.rustdesk.com/releases/download/console/so.tar.gz
            tar xzvf so.tar.gz
          popd
          # temporary use debug sign config
          sed -i "s/signingConfigs.release/signingConfigs.debug/g" ./flutter/android/app/build.gradle
          case ${{ matrix.job.target }} in
            aarch64-linux-android)
              mkdir -p ./flutter/android/app/src/main/jniLibs/arm64-v8a
              cp ./target/${{ matrix.job.target }}/release/liblibrustdesk.so ./flutter/android/app/src/main/jniLibs/arm64-v8a/librustdesk.so
              # build flutter
              pushd flutter
              flutter build apk --release --target-platform android-arm64 --split-per-abi
              mv build/app/outputs/flutter-apk/app-arm64-v8a-release.apk ../rustdesk-${{ env.VERSION }}-${{ matrix.job.target }}-release.apk
            ;;
            armv7-linux-androideabi)
              mkdir -p ./flutter/android/app/src/main/jniLibs/armeabi-v7a
              cp ./target/${{ matrix.job.target }}/release/liblibrustdesk.so ./flutter/android/app/src/main/jniLibs/armeabi-v7a/librustdesk.so
              # build flutter
              pushd flutter
              flutter build apk --release --target-platform android-arm --split-per-abi
              mv build/app/outputs/flutter-apk/app-armeabi-v7a-release.apk ../rustdesk-${{ env.VERSION }}-${{ matrix.job.target }}-release.apk
            ;;
          esac
          popd
          mkdir -p signed-apk; pushd signed-apk
          mv ../rustdesk-${{ env.VERSION }}-${{ matrix.job.target }}-release.apk .
      
  build-rustdesk-lib-linux-amd64:
    needs: [generate-bridge-linux, build-vcpkg-deps-linux]
    name: build-rust-lib ${{ matrix.job.target }} (${{ matrix.job.os }}) [${{ matrix.job.extra-build-features }}]
    runs-on: ${{ matrix.job.os }}
    strategy:
      fail-fast: true
      matrix:
        # use a high level qemu-user-static
        job:
          # - { target: i686-unknown-linux-gnu      , os: ubuntu-20.04, use-cross: true }
          # - { target: i686-unknown-linux-musl     , os: ubuntu-20.04, use-cross: true }
          - {
              arch: x86_64,
              target: x86_64-unknown-linux-gnu,
              os: ubuntu-20.04,
              extra-build-features: "",
            }
          - {
              arch: x86_64,
              target: x86_64-unknown-linux-gnu,
              os: ubuntu-20.04,
              extra-build-features: "flatpak",
            }
          - {
              arch: x86_64,
              target: x86_64-unknown-linux-gnu,
              os: ubuntu-20.04,
              extra-build-features: "appimage",
            }
          # - { target: x86_64-unknown-linux-musl   , os: ubuntu-20.04, use-cross: true }
    steps:
      - name: Maximize build space
        run: |
          sudo rm -rf /opt/ghc
          sudo rm -rf /usr/local/lib/android
          sudo rm -rf /usr/share/dotnet
          sudo apt update -y
          sudo apt install qemu-user-static

      - name: Checkout source code
        uses: actions/checkout@v3

      - name: Set Swap Space
        uses: pierotofy/set-swap-space@master
        with:
          swap-size-gb: 12

      - name: Free Space
        run: |
          df

      - name: Install Rust toolchain
        uses: actions-rs/toolchain@v1
        with:
          toolchain: stable
          target: ${{ matrix.job.target }}
          override: true
          profile: minimal # minimal component installation (ie, no documentation)

      - uses: Swatinem/rust-cache@v2
        with:
          prefix-key: rustdesk-lib-cache
          key: ${{ matrix.job.target }}-${{ matrix.job.extra-build-features }}
          cache-directories: "/opt/rust-registry"

      - name: Install Rust toolchain
        uses: actions-rs/toolchain@v1
        with:
          toolchain: stable
          target: ${{ matrix.job.target }}
          override: true
          profile: minimal # minimal component installation (ie, no documentation)

      - name: Install local registry
        run: |
          mkdir -p /opt/rust-registry
          cargo install cargo-local-registry

      - name: Build local registry
        uses: nick-fields/retry@v2
        id: build-local-registry
        continue-on-error: true
        with:
          max_attempts: 3
          timeout_minutes: 15
          retry_on: error
          command: cargo local-registry --sync ./Cargo.lock /opt/rust-registry

      - name: Disable rust bridge build
        run: |
          sed -i "s/gen_flutter_rust_bridge();/\/\//g" build.rs
          # only build cdylib
          sed -i  "s/\[\"cdylib\", \"staticlib\", \"rlib\"\]/\[\"cdylib\"\]/g" Cargo.toml

      - name: Restore bridge files
        uses: actions/download-artifact@master
        with:
          name: bridge-artifact
          path: ./

      - name: Restore vcpkg files
        uses: actions/download-artifact@master
        with:
          name: vcpkg-artifact-${{ matrix.job.arch }}
          path: /opt/artifacts/vcpkg/installed

      - uses: Kingtous/run-on-arch-action@amd64-support
        name: Build rustdesk library for ${{ matrix.job.arch }}
        id: vcpkg
        with:
          arch: ${{ matrix.job.arch }}
          distro: ubuntu18.04
          # not ready yet
          # distro: ubuntu18.04-rustdesk
          githubToken: ${{ github.token }}
          setup: |
            ls -l "${PWD}"
            ls -l /opt/artifacts/vcpkg/installed
          dockerRunArgs: |
            --volume "${PWD}:/workspace"
            --volume "/opt/artifacts:/opt/artifacts"
            --volume "/opt/rust-registry:/opt/rust-registry"
          shell: /bin/bash
          install: |
            apt update -y
            echo -e "installing deps"
            apt-get -qq install -y  git curl wget nasm yasm libgtk-3-dev clang libxcb-randr0-dev libxdo-dev libxfixes-dev libxcb-shape0-dev libxcb-xfixes0-dev libasound2-dev libpulse-dev cmake libclang-dev ninja-build libappindicator3-dev libgstreamer1.0-dev libgstreamer-plugins-base1.0-dev libvdpau-dev libva-dev libclang-dev llvm-dev libclang-10-dev llvm-10-dev pkg-config tree g++ gcc libvpx-dev tree > /dev/null
            # we have libopus compiled by us.
            apt remove -y libopus-dev || true
            # output devs
            ls -l ./
            tree -L 3 /opt/artifacts/vcpkg/installed
          run: |
            # disable git safe.directory
            git config --global --add safe.directory "*"
            # rust
            pushd /opt
            wget -O rust.tar.gz https://static.rust-lang.org/dist/rust-1.64.0-${{ matrix.job.target }}.tar.gz
            tar -zxvf rust.tar.gz > /dev/null && rm rust.tar.gz
            cd rust-1.64.0-${{ matrix.job.target }} && ./install.sh
            rm -rf rust-1.64.0-${{ matrix.job.target }}
            # edit config
            mkdir -p ~/.cargo/
            echo """
              [source.crates-io]
              registry = 'https://github.com/rust-lang/crates.io-index'
              replace-with = 'local-registry'

              [source.local-registry]
              local-registry = '/opt/rust-registry/'
            """ > ~/.cargo/config
            cat ~/.cargo/config
            # start build
            pushd /workspace
            # mock 
            case "${{ matrix.job.arch }}" in
              x86_64)
                # no need mock on x86_64
                export VCPKG_ROOT=/opt/artifacts/vcpkg
                cargo build --lib --features hwcodec,flutter,${{ matrix.job.extra-build-features }} --release
                ;;
            esac

      - name: Upload Artifacts
        uses: actions/upload-artifact@master
        with:
          name: librustdesk-${{ matrix.job.arch }}-${{ matrix.job.extra-build-features }}.so
          path: target/release/liblibrustdesk.so

  build-rustdesk-lib-linux-arm:
    needs: [generate-bridge-linux, build-vcpkg-deps-linux]
    name: build-rust-lib ${{ matrix.job.target }} (${{ matrix.job.os }}) [${{ matrix.job.extra-build-features }}]
    runs-on: ${{ matrix.job.os }}
    strategy:
      fail-fast: true
      matrix:
        # use a high level qemu-user-static
        job:
          - {
              arch: aarch64,
              target: aarch64-unknown-linux-gnu,
              os: ubuntu-20.04,
              use-cross: true,
              extra-build-features: "",
            }
          - {
              arch: aarch64,
              target: aarch64-unknown-linux-gnu,
              os: ubuntu-18.04, # just for naming package, not running host
              use-cross: true,
              extra-build-features: "appimage",
            }
          # - { arch: aarch64, target: aarch64-unknown-linux-gnu   , os: ubuntu-20.04, use-cross: true, extra-build-features: "flatpak" }
          # - {
          #     arch: armv7,
          #     target: arm-unknown-linux-gnueabihf,
          #     os: ubuntu-20.04,
          #     use-cross: true,
          #     extra-build-features: "",
          #   }
          # - { arch: armv7, target: arm-unknown-linux-gnueabihf , os: ubuntu-20.04, use-cross: true, extra-build-features: "flatpak" }
          # - { target: arm-unknown-linux-musleabihf, os: ubuntu-20.04, use-cross: true }
    steps:
      - name: Maximize build space
        run: |
          sudo rm -rf /opt/ghc
          sudo rm -rf /usr/local/lib/android
          sudo rm -rf /usr/share/dotnet
          sudo apt update -y
          sudo apt install qemu-user-static

      - name: Checkout source code
        uses: actions/checkout@v3

      - name: Set Swap Space
        uses: pierotofy/set-swap-space@master
        with:
          swap-size-gb: 12

      - name: Free Space
        run: |
          df

      - name: Install Rust toolchain
        uses: actions-rs/toolchain@v1
        with:
          toolchain: stable
          target: ${{ matrix.job.target }}
          override: true
          profile: minimal # minimal component installation (ie, no documentation)

      - name: Install Rust toolchain
        uses: actions-rs/toolchain@v1
        with:
          toolchain: stable
          target: ${{ matrix.job.target }}
          override: true
          profile: minimal # minimal component installation (ie, no documentation)

      - uses: Swatinem/rust-cache@v2
        with:
          prefix-key: rustdesk-lib-cache
          key: ${{ matrix.job.target }}-${{ matrix.job.extra-build-features }}
          cache-directories: "/opt/rust-registry"

      - name: Install local registry
        run: |
          mkdir -p /opt/rust-registry
          cargo install cargo-local-registry

      - name: Build local registry
        uses: nick-fields/retry@v2
        id: build-local-registry
        continue-on-error: true
        with:
          max_attempts: 3
          timeout_minutes: 15
          retry_on: error
          command: cargo local-registry --sync ./Cargo.lock /opt/rust-registry

      - name: Disable rust bridge build
        run: |
          sed -i "s/gen_flutter_rust_bridge();/\/\//g" build.rs
          # only build cdylib
          sed -i  "s/\[\"cdylib\", \"staticlib\", \"rlib\"\]/\[\"cdylib\"\]/g" Cargo.toml

      - name: Restore bridge files
        uses: actions/download-artifact@master
        with:
          name: bridge-artifact
          path: ./

      - name: Restore vcpkg files
        uses: actions/download-artifact@master
        with:
          name: vcpkg-artifact-${{ matrix.job.arch }}
          path: /opt/artifacts/vcpkg/installed

      - uses: Kingtous/run-on-arch-action@amd64-support
        name: Build rustdesk library for ${{ matrix.job.arch }}
        id: vcpkg
        with:
          arch: ${{ matrix.job.arch }}
          distro: ubuntu18.04-rustdesk
          githubToken: ${{ github.token }}
          setup: |
            ls -l "${PWD}"
            ls -l /opt/artifacts/vcpkg/installed
          dockerRunArgs: |
            --volume "${PWD}:/workspace"
            --volume "/opt/artifacts:/opt/artifacts"
            --volume "/opt/rust-registry:/opt/rust-registry"
          shell: /bin/bash
          install: |
            apt update -y
            echo -e "installing deps"
            apt-get -qq install -y  git curl wget nasm yasm libgtk-3-dev clang libxcb-randr0-dev libxdo-dev libxfixes-dev libxcb-shape0-dev libxcb-xfixes0-dev libasound2-dev libpulse-dev cmake libclang-dev ninja-build libappindicator3-dev libgstreamer1.0-dev libgstreamer-plugins-base1.0-dev libvdpau-dev libva-dev libclang-dev llvm-dev libclang-10-dev llvm-10-dev pkg-config tree g++ gcc libvpx-dev tree > /dev/null
            # we have libopus compiled by us.
            apt remove -y libopus-dev || true
            # output devs
            ls -l ./
            tree -L 3 /opt/artifacts/vcpkg/installed
          run: |
            # disable git safe.directory
            git config --global --add safe.directory "*"
            # rust
            pushd /opt
            wget -O rust.tar.gz https://static.rust-lang.org/dist/rust-1.64.0-${{ matrix.job.target }}.tar.gz
            tar -zxvf rust.tar.gz > /dev/null && rm rust.tar.gz
            cd rust-1.64.0-${{ matrix.job.target }} && ./install.sh
            rm -rf rust-1.64.0-${{ matrix.job.target }}
            # edit config
            mkdir -p ~/.cargo/
            echo """
              [source.crates-io]
              registry = 'https://github.com/rust-lang/crates.io-index'
              replace-with = 'local-registry'

              [source.local-registry]
              local-registry = '/opt/rust-registry/'
            """ > ~/.cargo/config
            cat ~/.cargo/config
            # start build
            pushd /workspace
            # mock 
            case "${{ matrix.job.arch }}" in
              aarch64)
                cp -r /opt/artifacts/vcpkg/installed/lib/* /usr/lib/aarch64-linux-gnu/
                cp -r /opt/artifacts/vcpkg/installed/include/* /usr/include/
                ls -l /opt/artifacts/vcpkg/installed/lib/
                mkdir -p /vcpkg/installed/arm64-linux
                ln -s /usr/lib/aarch64-linux-gnu  /vcpkg/installed/arm64-linux/lib
                ln -s /usr/include /vcpkg/installed/arm64-linux/include
                export VCPKG_ROOT=/vcpkg
                # disable hwcodec for compilation
                cargo build --lib --features flutter,${{ matrix.job.extra-build-features }} --release
                ;;
              armv7)
                cp -r /opt/artifacts/vcpkg/installed/lib/* /usr/lib/arm-linux-gnueabihf/
                cp -r /opt/artifacts/vcpkg/installed/include/* /usr/include/
                mkdir -p /vcpkg/installed/arm-linux
                ln -s /usr/lib/arm-linux-gnueabihf  /vcpkg/installed/arm-linux/lib
                ln -s /usr/include /vcpkg/installed/arm-linux/include
                export VCPKG_ROOT=/vcpkg
                # disable hwcodec for compilation
                cargo build --lib --features flutter,${{ matrix.job.extra-build-features }} --release
                ;;
            esac

      - name: Upload Artifacts
        uses: actions/upload-artifact@master
        with:
          name: librustdesk-${{ matrix.job.arch }}-${{ matrix.job.extra-build-features }}.so
          path: target/release/liblibrustdesk.so

  build-rustdesk-linux-arm:
    needs: [build-rustdesk-lib-linux-arm]
    name: build-rustdesk ${{ matrix.job.target }} (${{ matrix.job.os }}) [${{ matrix.job.extra-build-features }}]
    runs-on: ubuntu-20.04 # 20.04 has more performance on arm build
    strategy:
      fail-fast: true
      matrix:
        job:
          - {
              arch: aarch64,
              target: aarch64-unknown-linux-gnu,
              os: ubuntu-18.04, # just for naming package, not running host
              use-cross: true,
              extra-build-features: "",
            }
          - {
              arch: aarch64,
              target: aarch64-unknown-linux-gnu,
              os: ubuntu-18.04, # just for naming package, not running host
              use-cross: true,
              extra-build-features: "appimage",
            }
          # - {
          #     arch: aarch64,
          #     target: aarch64-unknown-linux-gnu,
          #     os: ubuntu-18.04, # just for naming package, not running host
          #     use-cross: true,
          #     extra-build-features: "flatpak",
          #   }
          # - { arch: armv7, target: arm-unknown-linux-gnueabihf , os: ubuntu-20.04, use-cross: true, extra-build-features: "" }
          # - { arch: armv7, target: arm-unknown-linux-gnueabihf , os: ubuntu-20.04, use-cross: true, extra-build-features: "flatpak" }
          # - { target: arm-unknown-linux-musleabihf, os: ubuntu-20.04, use-cross: true }
    steps:
      - name: Checkout source code
        uses: actions/checkout@v3

      - name: Restore bridge files
        uses: actions/download-artifact@master
        with:
          name: bridge-artifact
          path: ./

      - name: Prepare env
        run: |
          sudo apt update -y
          sudo apt-get -qq install -y git curl wget nasm yasm libgtk-3-dev libarchive-tools
          mkdir -p ./target/release/

      - name: Restore the rustdesk lib file
        uses: actions/download-artifact@master
        with:
          name: librustdesk-${{ matrix.job.arch }}-${{ matrix.job.extra-build-features }}.so
          path: ./target/release/

      - name: Download Flutter
        shell: bash
        run: |
          # disable git safe.directory
          git config --global --add safe.directory "*"
          pushd /opt
          # clone repo and reset to flutter 3.0.5
          git clone https://github.com/sony/flutter-elinux.git || true
          pushd flutter-elinux
            # reset to flutter 3.0.5
            git fetch
            git reset --hard b09a90eee643859ce4e676839227edd9fd3feba8 
          popd

      - uses: Kingtous/run-on-arch-action@amd64-support
        name: Build rustdesk binary for ${{ matrix.job.arch }}
        id: vcpkg
        with:
          arch: ${{ matrix.job.arch }}
          distro: ubuntu18.04-rustdesk
          githubToken: ${{ github.token }}
          setup: |
            ls -l "${PWD}"
          dockerRunArgs: |
            --volume "${PWD}:/workspace"
            --volume "/opt/artifacts:/opt/artifacts"
            --volume "/opt/flutter-elinux:/opt/flutter-elinux"
          shell: /bin/bash
          install: |
            apt update -y
            apt-get -qq install -y git cmake g++ gcc build-essential nasm yasm curl unzip xz-utils python3 wget pkg-config ninja-build pkg-config libgtk-3-dev liblzma-dev clang libappindicator3-dev rpm
          run: |
            # disable git safe.directory
            git config --global --add safe.directory "*"
            pushd /workspace
            # we use flutter-elinux to build our rustdesk
            sed -i "s/flutter build linux --release/flutter-elinux build linux/g" ./build.py
            # Setup flutter-elinux
            export PATH=/opt/flutter-elinux/bin:$PATH
            flutter-elinux doctor -v
            # edit to corresponding arch
            case ${{ matrix.job.arch }} in
              aarch64)
                sed -i "s/Architecture: amd64/Architecture: arm64/g" ./build.py
                sed -i "s/x64\/release/arm64\/release/g" ./build.py
              ;;
              armv7)
                sed -i "s/Architecture: amd64/Architecture: arm/g" ./build.py
                sed -i "s/x64\/release/arm\/release/g" ./build.py
              ;;
            esac
            python3 ./build.py --flutter --hwcodec --skip-cargo

  build-rustdesk-linux-amd64:
    needs: [build-rustdesk-lib-linux-amd64]
    name: build-rustdesk ${{ matrix.job.target }} (${{ matrix.job.os }}) [${{ matrix.job.extra-build-features }}]
    runs-on: ubuntu-20.04
    strategy:
      fail-fast: true
      matrix:
        job:
          # - { target: i686-unknown-linux-gnu      , os: ubuntu-20.04, use-cross: true }
          # - { target: i686-unknown-linux-musl     , os: ubuntu-20.04, use-cross: true }
          - {
              arch: x86_64,
              target: x86_64-unknown-linux-gnu,
              os: ubuntu-18.04,
              extra-build-features: "",
            }
          - {
              arch: x86_64,
              target: x86_64-unknown-linux-gnu,
              os: ubuntu-18.04,
              extra-build-features: "flatpak",
            }
          - {
              arch: x86_64,
              target: x86_64-unknown-linux-gnu,
              os: ubuntu-18.04,
              extra-build-features: "appimage",
            }
          # - { target: x86_64-unknown-linux-musl   , os: ubuntu-20.04, use-cross: true }
    steps:
      - name: Checkout source code
        uses: actions/checkout@v3

      - name: Restore bridge files
        uses: actions/download-artifact@master
        with:
          name: bridge-artifact
          path: ./

      - name: Prepare env
        run: |
          sudo apt update -y
          sudo apt-get -qq install -y git curl wget nasm yasm libgtk-3-dev libarchive-tools
          mkdir -p ./target/release/

      - name: Restore the rustdesk lib file
        uses: actions/download-artifact@master
        with:
          name: librustdesk-${{ matrix.job.arch }}-${{ matrix.job.extra-build-features }}.so
          path: ./target/release/

      - uses: Kingtous/run-on-arch-action@amd64-support
        name: Build rustdesk binary for ${{ matrix.job.arch }}
        id: vcpkg
        with:
          arch: ${{ matrix.job.arch }}
          distro: ubuntu18.04
          githubToken: ${{ github.token }}
          setup: |
            ls -l "${PWD}"
          dockerRunArgs: |
            --volume "${PWD}:/workspace"
            --volume "/opt/artifacts:/opt/artifacts"
          shell: /bin/bash
          install: |
            apt update -y
            apt-get -qq install -y git cmake g++ gcc build-essential nasm yasm curl unzip xz-utils python3 wget pkg-config ninja-build pkg-config libgtk-3-dev liblzma-dev clang libappindicator3-dev rpm
          run: |
            # disable git safe.directory
            git config --global --add safe.directory "*"
            # Setup Flutter
            pushd /opt
            wget https://storage.googleapis.com/flutter_infra_release/releases/stable/linux/flutter_linux_${{ env.FLUTTER_VERSION }}-stable.tar.xz
            tar xf flutter_linux_${{ env.FLUTTER_VERSION }}-stable.tar.xz
            ls -l .
            export PATH=/opt/flutter/bin:$PATH
            flutter doctor -v
            pushd /workspace
            python3 ./build.py --flutter --hwcodec --skip-cargo
