name: Build the flutter version of the RustDesk 

on:
  workflow_call:
    inputs:
      upload-artifact:
        type: boolean
        default: true
      upload-tag:
        type: string
        default: "nightly"

env:
  CARGO_NDK_VERSION: "3.1.2"
  LLVM_VERSION: "15.0.6"
  FLUTTER_VERSION: "3.10.6"
  FLUTTER_RUST_BRIDGE_VERSION: "1.75.3"
  # for arm64 linux
  FLUTTER_ELINUX_VERSION: "3.10.6"
  FLUTTER_ELINUX_COMMIT_ID: "410b3ca42f2cd0c485edf517a1666652bab442d4"
  TAG_NAME: "${{ inputs.upload-tag }}"
  # vcpkg version: 2023.04.15
  # for multiarch gcc compatibility
  VCPKG_COMMIT_ID: "501db0f17ef6df184fcdbfbe0f87cde2313b6ab1"
  VERSION: "1.2.3"
  NDK_VERSION: "r25c"
  #signing keys env variable checks
  ANDROID_SIGNING_KEY: '${{ secrets.ANDROID_SIGNING_KEY }}'
  MACOS_P12_BASE64: '${{ secrets.MACOS_P12_BASE64 }}'
  # To make a custom build with your own servers set the below secret values
  RS_PUB_KEY: '${{ secrets.RS_PUB_KEY }}'
  RENDEZVOUS_SERVER: '${{ secrets.RENDEZVOUS_SERVER }}'
  UPLOAD_ARTIFACT: "${{ inputs.upload-artifact }}"

jobs:
  build-for-windows-flutter:
    name: ${{ matrix.job.target }} (${{ matrix.job.os }})
    runs-on: ${{ matrix.job.os }}
    strategy:
      fail-fast: false
      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, arch: x86_64 }
          # - { target: aarch64-pc-windows-msvc, os: windows-2019, arch: aarch64 }
    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.7.0-rustdesk/windows-x64-release-flutter.zip -OutFile windows-x64-flutter-release.zip
      #     Expand-Archive windows-x64-flutter-release.zip -DestinationPath engine
      #     mv -Force engine/*  C:/hostedtoolcache/windows/flutter/stable-${{ env.FLUTTER_VERSION }}-x64/bin/cache/artifacts/engine/windows-x64-release/

      - 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
        run: |
          git config --global core.longpaths true
          cargo install flutter_rust_bridge_codegen --version ${{ env.FLUTTER_RUST_BRIDGE_VERSION }} --features "uuid"
          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: Install vcpkg dependencies
        run: |
          cd C:\
          git clone https://github.com/Kingtous/rustdesk_thirdpary_lib --depth=1 
          
      - name: Build rustdesk
        env:
          VCPKG_ROOT: C:\rustdesk_thirdpary_lib\vcpkg
        run: python3 .\build.py --portable --hwcodec --flutter --feature IddDriver

      - name: find Runner.res
        # Windows: find Runner.res (compiled from ./flutter/windows/runner/Runner.rc), copy to ./Runner.res
        # Runner.rc does not contain actual version, but Runner.res does
        continue-on-error: true
        shell: bash
        run: |
          runner_res=$(find . -name "Runner.res");
          if [ "$runner_res" == "" ]; then
            echo "Runner.res: not found";
          else
            echo "Runner.res: $runner_res";
            cp $runner_res ./libs/portable/Runner.res;
            echo "list ./libs/portable/Runner.res";
            ls -l ./libs/portable/Runner.res;
          fi

      - name: Sign rustdesk files
        uses: GermanBluefox/code-sign-action@v7
        if: env.UPLOAD_ARTIFACT == 'true'
        with:
          certificate: '${{ secrets.WINDOWS_PFX_BASE64 }}'
          password: '${{ secrets.WINDOWS_PFX_PASSWORD }}'
          certificatesha1: '${{ secrets.WINDOWS_PFX_SHA1_THUMBPRINT }}'
          # certificatename: '${{ secrets.CERTNAME }}'
          folder: './flutter/build/windows/runner/Release/'
          recursive: true

      - name: Build self-extracted executable
        shell: bash
        if: env.UPLOAD_ARTIFACT == 'true'
        run: |
          pushd ./libs/portable
          python3 ./generate.py -f ../../flutter/build/windows/runner/Release/ -o . -e ../../flutter/build/windows/runner/Release/rustdesk.exe
          popd
          mkdir -p ./SignOutput
          mv ./target/release/rustdesk-portable-packer.exe ./SignOutput/rustdesk-${{ env.VERSION }}-${{ matrix.job.arch }}.exe

      - name: Sign rustdesk self-extracted file
        uses: GermanBluefox/code-sign-action@v7
        if: env.UPLOAD_ARTIFACT == 'true'
        with:
          certificate: '${{ secrets.WINDOWS_PFX_BASE64 }}'
          password: '${{ secrets.WINDOWS_PFX_PASSWORD }}'
          certificatesha1: '${{ secrets.WINDOWS_PFX_SHA1_THUMBPRINT }}'
          # certificatename: '${{ secrets.WINDOWS_PFX_NAME }}'
          folder: './SignOutput'
          recursive: false

      - name: Publish Release
        uses: softprops/action-gh-release@v1
        if: env.UPLOAD_ARTIFACT == 'true'
        with:
          prerelease: true
          tag_name: ${{ env.TAG_NAME }}
          files: |
            ./SignOutput/rustdesk-*.exe

  # The fallback for the flutter version, we use Sciter for 32bit Windows.
  build-for-windows-sciter:
    name: ${{ matrix.job.target }} (${{ matrix.job.os }})
    runs-on: ${{ matrix.job.os }}
    # Temporarily disable this action due to additional test is needed.
    # if: false 
    strategy:
      fail-fast: false
      matrix:
        job:
          # - { target: i686-pc-windows-msvc        , os: windows-2019                  }
          # - { target: x86_64-pc-windows-gnu       , os: windows-2019                  }
          - { target: i686-pc-windows-msvc, os: windows-2019, arch: x86 }
          # - { target: aarch64-pc-windows-msvc, os: windows-2019 }
    steps:
      - name: Checkout source code
        uses: actions/checkout@v3

      - name: Install LLVM and Clang
        uses: rustdesk-org/install-llvm-action-32bit@master
        with:
          version: ${{ env.LLVM_VERSION }}

      - name: Install Rust toolchain
        uses: actions-rs/toolchain@v1
        with:
          toolchain: nightly-${{ matrix.job.target }}
          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 }}-sciter

      - 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: |
          cd C:\
          git clone https://github.com/Kingtous/rustdesk_thirdpary_lib --depth=1 

      - name: Build rustdesk
        id: build
        shell: bash
        env:
          VCPKG_ROOT: C:\rustdesk_thirdpary_lib\vcpkg
        run: |
          python3 res/inline-sciter.py
          # Patch sciter x86
          sed -i 's/branch = "dyn"/branch = "dyn_x86"/g' ./Cargo.toml
          cargo build --features inline --release --bins
          mkdir -p ./Release
          mv ./target/release/rustdesk.exe ./Release/rustdesk.exe
          curl -LJ -o ./Release/sciter.dll https://github.com/c-smile/sciter-sdk/raw/master/bin.win/x32/sciter.dll
          echo "output_folder=./Release" >> $GITHUB_OUTPUT

      - name: find Runner.res
        # Windows: find Runner.res (compiled from ./flutter/windows/runner/Runner.rc), copy to ./Runner.res
        # Runner.rc does not contain actual version, but Runner.res does
        continue-on-error: true
        shell: bash
        run: |
          runner_res=$(find . -name "Runner.res");
          if [ "$runner_res" == "" ]; then
            echo "Runner.res: not found";
          else
            echo "Runner.res: $runner_res";
            cp $runner_res ./libs/portable/Runner.res;
            echo "list ./libs/portable/Runner.res";
            ls -l ./libs/portable/Runner.res;
          fi

      - name: Sign rustdesk files
        uses: GermanBluefox/code-sign-action@v7
        if: env.UPLOAD_ARTIFACT == 'true'
        with:
          certificate: '${{ secrets.WINDOWS_PFX_BASE64 }}'
          password: '${{ secrets.WINDOWS_PFX_PASSWORD }}'
          certificatesha1: '${{ secrets.WINDOWS_PFX_SHA1_THUMBPRINT }}'
          # certificatename: '${{ secrets.CERTNAME }}'
          folder: './Release/'
          recursive: true

      - name: Build self-extracted executable
        shell: bash
        run: |
          pushd ./libs/portable
          pip3 install -r requirements.txt
          python3 ./generate.py -f ../../Release/ -o . -e ../../Release/rustdesk.exe
          popd
          mkdir -p ./SignOutput
          mv ./target/release/rustdesk-portable-packer.exe ./SignOutput/rustdesk-${{ env.VERSION }}-${{ matrix.job.arch }}-sciter.exe
      
      - name: Sign rustdesk self-extracted file
        uses: GermanBluefox/code-sign-action@v7
        with:
          certificate: '${{ secrets.WINDOWS_PFX_BASE64 }}'
          password: '${{ secrets.WINDOWS_PFX_PASSWORD }}'
          certificatesha1: '${{ secrets.WINDOWS_PFX_SHA1_THUMBPRINT }}'
          # certificatename: '${{ secrets.WINDOWS_PFX_NAME }}'
          folder: './SignOutput'
          recursive: false

      - name: Publish Release
        uses: softprops/action-gh-release@v1
        if: env.UPLOAD_ARTIFACT == 'true'
        with:
          prerelease: true
          tag_name: ${{ env.TAG_NAME }}
          files: |
            ./SignOutput/rustdesk-*.exe

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

      - name: Import the codesign cert
        if: env.MACOS_P12_BASE64 != null
        uses: apple-actions/import-codesign-certs@v1
        with: 
          p12-file-base64: ${{ secrets.MACOS_P12_BASE64 }}
          p12-password: ${{ secrets.MACOS_P12_PASSWORD }}
          keychain: rustdesk
      
      - name: Check sign and import sign key
        if: env.MACOS_P12_BASE64 != null
        run: |
          security default-keychain -s rustdesk.keychain
          security find-identity -v

      - name: Import notarize key
        if: env.MACOS_P12_BASE64 != null
        uses: timheuer/base64-to-file@v1.2
        with:
          # https://gregoryszorc.com/docs/apple-codesign/stable/apple_codesign_rcodesign.html#notarizing-and-stapling
          fileName: rustdesk.json
          fileDir: ${{ github.workspace }}
          encodedString: ${{ secrets.MACOS_NOTARIZE_JSON }}
          
      - name: Install rcodesign tool
        if: env.MACOS_P12_BASE64 != null
        shell: bash
        run: | 
          pushd /tmp
          wget https://github.com/indygreg/apple-platform-rs/releases/download/apple-codesign%2F0.22.0/apple-codesign-0.22.0-macos-universal.tar.gz
          tar -zxvf apple-codesign-0.22.0-macos-universal.tar.gz
          mv apple-codesign-0.22.0-macos-universal/rcodesign /usr/local/bin
          popd

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

      - 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: |
          cargo install flutter_rust_bridge_codegen --version ${{ env.FLUTTER_RUST_BRIDGE_VERSION }} --features "uuid"
          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 --c-output ./flutter/macos/Runner/bridge_generated.h

      - 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 aom

      - 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 }}

      - name: Codesign app and create signed dmg
        if: env.MACOS_P12_BASE64 != null
        run: |
          security default-keychain -s rustdesk.keychain
          security unlock-keychain -p ${{ secrets.MACOS_P12_PASSWORD }} rustdesk.keychain
          # start sign the rustdesk.app and dmg
          rm rustdesk-${{ env.VERSION }}.dmg || true
          codesign --force --options runtime -s ${{ secrets.MACOS_CODESIGN_IDENTITY }} --deep --strict ./flutter/build/macos/Build/Products/Release/RustDesk.app -vvv
          create-dmg --icon "RustDesk.app" 200 190 --hide-extension "RustDesk.app" --window-size 800 400 --app-drop-link 600 185 rustdesk-${{ env.VERSION }}.dmg ./flutter/build/macos/Build/Products/Release/RustDesk.app
          codesign --force --options runtime -s ${{ secrets.MACOS_CODESIGN_IDENTITY }} --deep --strict rustdesk-${{ env.VERSION }}.dmg -vvv
          # notarize the rustdesk-${{ env.VERSION }}.dmg
          rcodesign notary-submit --api-key-path ${{ github.workspace }}/rustdesk.json  --staple rustdesk-${{ env.VERSION }}.dmg

      - name: Rename rustdesk
        run: |
          for name in rustdesk*??.dmg; do
              mv "$name" "${name%%.dmg}-${{ matrix.job.arch }}.dmg"
          done

      - name: Publish DMG package
        if: env.UPLOAD_ARTIFACT == 'true'
        uses: softprops/action-gh-release@v1
        with:
          prerelease: true
          tag_name: ${{ env.TAG_NAME }}
          files: |
            rustdesk*-${{ matrix.job.arch }}.dmg

  build-vcpkg-deps-linux:
    uses: ./.github/workflows/vcpkg-deps-linux.yml

  generate-bridge-linux:
    uses: ./.github/workflows/bridge.yml

  build-rustdesk-ios:
    if: ${{ inputs.upload-artifact }}
    needs: [generate-bridge-linux]
    name: build rustdesk ios ipa ${{ matrix.job.target }} (${{ matrix.job.os }}) [${{ matrix.job.extra-build-features }}]
    runs-on: ${{ matrix.job.os }}
    strategy:
      fail-fast: false
      matrix:
        job:
          - {
              arch: aarch64,
              target: aarch64-apple-ios,
              os: macos-latest,
              extra-build-features: "",
            }
    steps:
      - name: Install dependencies
        run: |
          brew install nasm yasm
      - name: Checkout source code
        uses: actions/checkout@v3
      - name: Install flutter
        uses: subosito/flutter-action@v2
        with:
          channel: "stable"
          flutter-version: ${{ env.FLUTTER_VERSION }}

      - name: Clone deps
        shell: bash
        run: |
          pushd /opt
          sudo git clone https://github.com/rustdesk-org/rustdesk_thirdparty_lib.git --depth=1

      - 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
          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 }}

      - name: Install flutter rust bridge deps
        shell: bash
        run: |
          cargo install flutter_rust_bridge_codegen --version ${{ env.FLUTTER_RUST_BRIDGE_VERSION }} --features "uuid"
          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 --c-output ./flutter/ios/Runner/bridge_generated.h

      - name: Build rustdesk lib
        env:
          VCPKG_ROOT: /opt/rustdesk_thirdparty_lib/vcpkg
        run: |
          rustup target add ${{ matrix.job.target }} 
          cargo build --features flutter --release --target aarch64-apple-ios --lib

      - name: Build rustdesk
        shell: bash
        run: |
          pushd flutter
          # flutter build ipa --release --obfuscate --split-debug-info=./split-debug-info --no-codesign
          # for easy debugging
          flutter build ipa --release --no-codesign
      
      # - name: Upload Artifacts
      #   # if: env.ANDROID_SIGNING_KEY != null && env.UPLOAD_ARTIFACT == 'true'
      #   uses: actions/upload-artifact@master
      #   with:
      #     name: rustdesk-${{ env.VERSION }}-${{ matrix.job.arch }}.apk
      #     path: flutter/build/ios/ipa/*.ipa

      # - name: Publish ipa package
      #   # if: env.ANDROID_SIGNING_KEY != null && env.UPLOAD_ARTIFACT == 'true'
      #   uses: softprops/action-gh-release@v1
      #   with:
      #     prerelease: true
      #     tag_name: ${{ env.TAG_NAME }}
      #     files: |
      #       flutter/build/ios/ipa/*.ipa
    

  build-rustdesk-android:
    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: false
      matrix:
        job:
          - {
              arch: aarch64,
              target: aarch64-linux-android,
              os: ubuntu-20.04,
              extra-build-features: "",
              openssl-arch: android-arm64
            }
          - {
              arch: armv7,
              target: armv7-linux-androideabi,
              os: ubuntu-20.04,
              extra-build-features: "",
              openssl-arch: android-arm
            }
    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 libpam0g-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: ${{ env.NDK_VERSION }}
          add-to-path: true

      - name: Clone deps
        shell: bash
        run: |
          pushd /opt
          git clone https://github.com/rustdesk-org/rustdesk_thirdparty_lib.git --depth=1

      - 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: 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/rustdesk_thirdparty_lib/vcpkg
        run: |
          rustup target add ${{ matrix.job.target }} 
          cargo install cargo-ndk --version ${{ env.CARGO_NDK_VERSION }}
          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
          # 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 /opt/rustdesk_thirdparty_lib/android/app/src/main/jniLibs/arm64-v8a/*.so ./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.arch }}.apk
            ;;
            armv7-linux-androideabi)
              mkdir -p ./flutter/android/app/src/main/jniLibs/armeabi-v7a
              cp /opt/rustdesk_thirdparty_lib/android/app/src/main/jniLibs/armeabi-v7a/*.so ./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.arch }}.apk
            ;;
          esac
          popd
          mkdir -p signed-apk; pushd signed-apk
          mv ../rustdesk-${{ env.VERSION }}-${{ matrix.job.arch }}.apk .
      
      - uses: r0adkll/sign-android-release@v1
        name: Sign app APK
        if: env.ANDROID_SIGNING_KEY != null
        id: sign-rustdesk
        with:
          releaseDirectory: ./signed-apk
          signingKeyBase64: ${{ secrets.ANDROID_SIGNING_KEY }}
          alias: ${{ secrets.ANDROID_ALIAS }}
          keyStorePassword: ${{ secrets.ANDROID_KEY_STORE_PASSWORD }}
          keyPassword: ${{ secrets.ANDROID_KEY_PASSWORD }}
        env:
          # override default build-tools version (29.0.3) -- optional
          BUILD_TOOLS_VERSION: "30.0.2"

      - name: Upload Artifacts
        if: env.ANDROID_SIGNING_KEY != null && env.UPLOAD_ARTIFACT == 'true'
        uses: actions/upload-artifact@master
        with:
          name: rustdesk-${{ env.VERSION }}-${{ matrix.job.arch }}.apk
          path: ${{steps.sign-rustdesk.outputs.signedReleaseFile}}

      - name: Publish signed apk package
        if: env.ANDROID_SIGNING_KEY != null && env.UPLOAD_ARTIFACT == 'true'
        uses: softprops/action-gh-release@v1
        with:
          prerelease: true
          tag_name: ${{ env.TAG_NAME }}
          files: |
            ${{steps.sign-rustdesk.outputs.signedReleaseFile}}

      - name: Publish unsigned apk package
        if: env.ANDROID_SIGNING_KEY == null && env.UPLOAD_ARTIFACT == 'true'
        uses: softprops/action-gh-release@v1
        with:
          prerelease: true
          tag_name: ${{ env.TAG_NAME }}
          files: |
            signed-apk/rustdesk-${{ env.VERSION }}-${{ matrix.job.arch }}.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: false
      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: "",
              enable-headless: true
            }
          - {
              arch: x86_64,
              target: x86_64-unknown-linux-gnu,
              os: ubuntu-20.04,
              extra-build-features: "flatpak",
              enable-headless: false
            }
          - {
              arch: x86_64,
              target: x86_64-unknown-linux-gnu,
              os: ubuntu-20.04,
              extra-build-features: "appimage",
              enable-headless: false
            }
          # - { 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 -y

      - 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 -h
          free -m

      - 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: Save Rust toolchain version
        run: |
          RUST_TOOLCHAIN_VERSION=$(cargo --version | awk '{print $2}')
          echo "RUST_TOOLCHAIN_VERSION=$RUST_TOOLCHAIN_VERSION" >> $GITHUB_ENV

      - name: Disable rust bridge build
        run: |
          # 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: rustdesk-org/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"
          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 libpam0g-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
            # do not use rustup, because memory overflow in qemu
            wget -O rust.tar.gz https://static.rust-lang.org/dist/rust-${{env.RUST_TOOLCHAIN_VERSION}}-${{ matrix.job.target }}.tar.gz
            tar -zxvf rust.tar.gz > /dev/null && rm rust.tar.gz
            cd rust-${{env.RUST_TOOLCHAIN_VERSION}}-${{ matrix.job.target }} && ./install.sh
            rm -rf rust-${{env.RUST_TOOLCHAIN_VERSION}}-${{ matrix.job.target }}
            # edit config
            mkdir -p ~/.cargo/
            echo """
              [source.crates-io]
              registry = 'https://github.com/rust-lang/crates.io-index'
            """ > ~/.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
                export DEFAULT_FEAT=""
                if ${{ matrix.job.enable-headless }}; then
                  export DEFAULT_FEAT=linux_headless
                fi
                cargo build --lib --features hwcodec,flutter,flutter_texture_render,${{ matrix.job.extra-build-features }},$DEFAULT_FEAT --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:
    if: ${{ inputs.upload-artifact }}
    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: [self-hosted, Linux, ARM64]
    strategy:
      fail-fast: false
      matrix:
        # use a high level qemu-user-static
        job:
          - {
              arch: aarch64,
              target: aarch64-unknown-linux-gnu,
              os: ubuntu-20.04, # just for naming package, not running host
              use-cross: true,
              extra-build-features: "",
              enable-headless: true
            }
          - {
              arch: aarch64,
              target: aarch64-unknown-linux-gnu,
              os: ubuntu-20.04, # just for naming package, not running host
              use-cross: true,
              extra-build-features: "appimage",
              enable-headless: false
            }
          # - { arch: aarch64, target: aarch64-unknown-linux-gnu   , os: ubuntu-20.04, use-cross: true, extra-build-features: "flatpak" }
          # - {
          #     arch: armv7,
          #     target: armv7-unknown-linux-gnueabihf,
          #     os: ubuntu-20.04,
          #     use-cross: true,
          #     extra-build-features: "",
          #   }
          # - { arch: armv7, target: armv7-unknown-linux-gnueabihf , os: ubuntu-20.04, use-cross: true, extra-build-features: "appimage" }
          # - { 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 -y

      - 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 -h
          free -m

      - 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: Save Rust toolchain version
        run: |
          RUST_TOOLCHAIN_VERSION=$(cargo --version | awk '{print $2}')
          echo "RUST_TOOLCHAIN_VERSION=$RUST_TOOLCHAIN_VERSION" >> $GITHUB_ENV

      - name: Disable rust bridge build
        run: |
          # 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: rustdesk-org/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"
          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 libpam0g-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
            # do not use rustup, because memory overflow in qemu
            wget -O rust.tar.gz https://static.rust-lang.org/dist/rust-${{env.RUST_TOOLCHAIN_VERSION}}-${{ matrix.job.target }}.tar.gz
            tar -zxvf rust.tar.gz > /dev/null && rm rust.tar.gz
            cd rust-${{env.RUST_TOOLCHAIN_VERSION}}-${{ matrix.job.target }} && ./install.sh
            rm -rf rust-${{env.RUST_TOOLCHAIN_VERSION}}-${{ matrix.job.target }}
            # edit config
            mkdir -p ~/.cargo/
            echo """
              [source.crates-io]
              registry = 'https://github.com/rust-lang/crates.io-index'
            """ > ~/.cargo/config
            cat ~/.cargo/config
            # start build
            pushd /workspace
            export VCPKG_ROOT=/opt/artifacts/vcpkg
            export DEFAULT_FEAT=""
            if ${{ matrix.job.enable-headless }}; then
              export DEFAULT_FEAT=linux_headless
            fi
            export CARGO_INCREMENTAL=0
            cargo build --lib --features flutter,flutter_texture_render,${{ matrix.job.extra-build-features }},$DEFAULT_FEAT --release

      - 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-sciter-arm:
    if: ${{ inputs.upload-artifact }}
    needs: [build-vcpkg-deps-linux]
    name: build-rustdesk(sciter) ${{ matrix.job.target }} (${{ matrix.job.os }}) [${{ matrix.job.extra-build-features }}]
    runs-on: [self-hosted, Linux, ARM64]
    strategy:
      fail-fast: false
      matrix:
        # use a high level qemu-user-static
        job:
          - {
              arch: armv7,
              target: armv7-unknown-linux-gnueabihf,
              deb-arch: armhf,
              os: ubuntu-latest,
              use-cross: true,
              extra-build-features: "",
              enable-headless: true
            }
          # - { arch: armv7, target: armv7-unknown-linux-gnueabihf , os: ubuntu-20.04, use-cross: true, extra-build-features: "appimage" }
          # - { 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 -y

      - 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 -h
          free -m

      - 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: Save Rust toolchain version
        run: |
          RUST_TOOLCHAIN_VERSION=$(cargo --version | awk '{print $2}')
          echo "RUST_TOOLCHAIN_VERSION=$RUST_TOOLCHAIN_VERSION" >> $GITHUB_ENV

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

      - uses: rustdesk-org/run-on-arch-action@amd64-support
        name: Build rustdesk sciter 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"
          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 libclang-dev
            apt-get -qq install -y libdbus-1-dev pkg-config nasm yasm libglib2.0-dev libxcb-randr0-dev libxdo-dev libxfixes-dev libxcb-shape0-dev libxcb-xfixes0-dev libasound2-dev 
            apt-get -qq install -y libpulse-dev libgstreamer1.0-dev libgstreamer-plugins-base1.0-dev libvpx-dev libvdpau-dev libva-dev libpam0g-dev
          run: |
            # disable git safe.directory
            git config --global --add safe.directory "*"
            # rust
            pushd /opt
            # do not use rustup, because memory overflow in qemu
            wget -O rust.tar.gz https://static.rust-lang.org/dist/rust-${{env.RUST_TOOLCHAIN_VERSION}}-${{ matrix.job.target }}.tar.gz
            tar -zxvf rust.tar.gz > /dev/null && rm rust.tar.gz
            cd rust-${{env.RUST_TOOLCHAIN_VERSION}}-${{ matrix.job.target }} && ./install.sh
            rm -rf rust-${{env.RUST_TOOLCHAIN_VERSION}}-${{ matrix.job.target }}
            # edit config
            mkdir -p ~/.cargo/
            echo """
              [source.crates-io]
              registry = 'https://github.com/rust-lang/crates.io-index'
            """ > ~/.cargo/config
            cat ~/.cargo/config
            
            # build
            pushd /workspace
            python3 ./res/inline-sciter.py
            export VCPKG_ROOT=/opt/artifacts/vcpkg
            export ARCH=armhf
            export DEFAULT_FEAT=""
            export CARGO_INCREMENTAL=0
            if ${{ matrix.job.enable-headless }}; then
              export DEFAULT_FEAT=linux_headless
            fi
            cargo build --features inline,${{ matrix.job.extra-build-features }},$DEFAULT_FEAT --release --bins
            # package
            mkdir -p ./Release
            mv ./target/release/rustdesk ./Release/rustdesk
            wget -O ./Release/libsciter-gtk.so https://github.com/c-smile/sciter-sdk/raw/master/bin.lnx/arm32/libsciter-gtk.so
            ./build.py --package ./Release

      - name: Rename rustdesk
        shell: bash
        run: |
          for name in rustdesk*??.deb; do
              # use cp to duplicate deb files to fit other packages.
              cp "$name" "${name%%.deb}-${{ matrix.job.arch }}-sciter.deb"
          done

      - name: Publish debian package
        if: matrix.job.extra-build-features == '' && env.UPLOAD_ARTIFACT == 'true'
        uses: softprops/action-gh-release@v1
        with:
          prerelease: true
          tag_name: ${{ env.TAG_NAME }}
          files: |
            rustdesk-${{ env.VERSION }}-${{ matrix.job.arch }}-sciter.deb

      - name: Upload Artifact
        uses: actions/upload-artifact@master
        if: ${{ contains(matrix.job.extra-build-features, 'flatpak') }}
        with:
          name: rustdesk-${{ env.VERSION }}-${{ matrix.job.arch }}-sciter.deb
          path: rustdesk-${{ env.VERSION }}-${{ matrix.job.arch }}-sciter.deb

  build-rustdesk-linux-arm:
    if: ${{ inputs.upload-artifact }}
    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: false
      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: armv7-unknown-linux-gnueabihf , os: ubuntu-20.04, use-cross: true, extra-build-features: "" }
          # - { arch: armv7, target: armv7-unknown-linux-gnueabihf , os: ubuntu-20.04, use-cross: true, extra-build-features: "appimage" }
          # - { 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 ${{ env.FLUTTER_VERSION }}
          git clone https://github.com/sony/flutter-elinux.git || true
          pushd flutter-elinux
            git fetch
            git reset --hard ${{ env.FLUTTER_ELINUX_COMMIT_ID }} 
          popd

      - uses: rustdesk-org/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
            export PATH=/opt/flutter-elinux/bin:$PATH
            sed -i "s/flutter build linux --release/flutter-elinux build linux/g" ./build.py
            # Setup flutter-elinux. Run doctor to check if issues here.
            flutter-elinux doctor -v
            # Patch arm64 engine for flutter 3.6.0+
            flutter-elinux precache --linux
            pushd /tmp
            curl -O https://storage.googleapis.com/flutter_infra_release/releases/stable/linux/flutter_linux_${{ env.FLUTTER_ELINUX_VERSION }}-stable.tar.xz
            tar -xvf flutter_linux_${{ env.FLUTTER_ELINUX_VERSION }}-stable.tar.xz flutter/bin/cache/artifacts/engine/linux-x64/shader_lib
            cp -R flutter/bin/cache/artifacts/engine/linux-x64/shader_lib /opt/flutter-elinux/flutter/bin/cache/artifacts/engine/linux-arm64
            popd
            # edit to corresponding arch
            case ${{ matrix.job.arch }} in
              aarch64)
                export ARCH=arm64
                sed -i "s/x64\/release/arm64\/release/g" ./build.py
              ;;
              armv7)
                export ARCH=armhf
                sed -i "s/x64\/release/arm\/release/g" ./build.py
              ;;
            esac
            export CARGO_INCREMENTAL=0
            python3 ./build.py --flutter --hwcodec --skip-cargo
            # rpm package
            echo -e "start packaging fedora package"
            pushd /workspace
            case ${{ matrix.job.arch }} in
              armv7)
                sed -i "s/64bit/32bit/g" ./res/rpm-flutter.spec
                sed -i "s/linux\/x64/linux\/arm/g" ./res/rpm-flutter.spec
                ;;
              aarch64)
                sed -i "s/linux\/x64/linux\/arm64/g" ./res/rpm-flutter.spec
                ;;
            esac
            HBB=`pwd` rpmbuild ./res/rpm-flutter.spec -bb
            pushd ~/rpmbuild/RPMS/${{ matrix.job.arch }}
            mkdir -p /opt/artifacts/rpm
            for name in rustdesk*??.rpm; do
                mv "$name" "/opt/artifacts/rpm/${name%%.rpm}.rpm" 
            done
            # rpm suse package
            echo -e "start packaging suse package"
            pushd /workspace
            case ${{ matrix.job.arch }} in
              armv7)
                sed -i "s/64bit/32bit/g" ./res/rpm-flutter-suse.spec
                sed -i "s/linux\/x64/linux\/arm/g" ./res/rpm-flutter-suse.spec
                ;;
              aarch64)
                sed -i "s/linux\/x64/linux\/arm64/g" ./res/rpm-flutter-suse.spec
                ;;
            esac
            HBB=`pwd` rpmbuild ./res/rpm-flutter.spec -bb
            pushd ~/rpmbuild/RPMS/${{ matrix.job.arch }}
            mkdir -p /opt/artifacts/rpm
            for name in rustdesk*??.rpm; do
                mv "$name" "/opt/artifacts/rpm/${name%%.rpm}-suse.rpm" 
            done

      - name: Rename rustdesk
        shell: bash
        run: |
          for name in rustdesk*??.deb; do
              cp "$name" "${name%%.deb}-${{ matrix.job.arch }}.deb"
          done

      - name: Publish debian package
        if: matrix.job.extra-build-features == '' && env.UPLOAD_ARTIFACT == 'true'
        uses: softprops/action-gh-release@v1
        with:
          prerelease: true
          tag_name: ${{ env.TAG_NAME }}
          files: |
            rustdesk-${{ env.VERSION }}-${{ matrix.job.arch }}.deb
      
      - name: Build appimage package
        if: ${{ matrix.job.extra-build-features == 'appimage' }}
        shell: bash
        run: |
          # set-up appimage-builder
          pushd /tmp
          wget -O appimage-builder-x86_64.AppImage https://github.com/AppImageCrafters/appimage-builder/releases/download/v1.1.0/appimage-builder-1.1.0-x86_64.AppImage
          chmod +x appimage-builder-x86_64.AppImage
          sudo mv appimage-builder-x86_64.AppImage /usr/local/bin/appimage-builder
          popd
          # run appimage-builder
          pushd appimage
          sudo appimage-builder --skip-tests --recipe ./AppImageBuilder-${{ matrix.job.arch }}.yml

      - name: Publish appimage package
        if: matrix.job.extra-build-features == 'appimage' && env.UPLOAD_ARTIFACT == 'true'
        uses: softprops/action-gh-release@v1
        with:
          prerelease: true
          tag_name: ${{ env.TAG_NAME }}
          files: |
            ./appimage/rustdesk-${{ env.VERSION }}-*.AppImage

      - name: Upload Artifact
        uses: actions/upload-artifact@master
        if: ${{ contains(matrix.job.extra-build-features, 'flatpak') }}
        with:
          name: rustdesk-${{ env.VERSION }}-${{ matrix.job.arch }}.deb
          path: rustdesk-${{ env.VERSION }}-${{ matrix.job.arch }}.deb

      - name: Patch archlinux PKGBUILD
        if: ${{ matrix.job.extra-build-features == '' }}
        run: |
          sed -i "s/arch=('x86_64')/arch=('${{ matrix.job.arch }}')/g" res/PKGBUILD
          case ${{ matrix.job.arch }} in
              armv7)
                sed -i "s/linux\/x64/linux\/arm/g" ./res/PKGBUILD
                ;;
              aarch64)
                sed -i "s/linux\/x64/linux\/arm64/g" ./res/PKGBUILD
                ;;
          esac

      # Temporary disable for there is no many archlinux arm hosts
      # - name: Build archlinux package
      #   if: ${{ matrix.job.extra-build-features == '' }}
      #   uses: vufa/arch-makepkg-action@master
      #   with:
      #     packages: >
      #       llvm
      #       clang
      #       libva
      #       libvdpau
      #       rust
      #       gstreamer
      #       unzip
      #       git
      #       cmake
      #       gcc
      #       curl
      #       wget
      #       yasm
      #       nasm
      #       zip
      #       make
      #       pkg-config
      #       clang
      #       gtk3
      #       xdotool
      #       libxcb
      #       libxfixes
      #       alsa-lib
      #       pipewire
      #       python
      #       ttf-arphic-uming
      #       libappindicator-gtk3
      #     scripts: |
      #       cd res && HBB=`pwd`/.. FLUTTER=1 makepkg -f

      # - name: Publish archlinux package
      #   if: ${{ matrix.job.extra-build-features == '' }}
      #   uses: softprops/action-gh-release@v1
      #   with:
      #     prerelease: true
      #     tag_name: ${{ env.TAG_NAME }}
      #     files: |
      #       res/rustdesk*.zst

      - name: Publish fedora package
        if: matrix.job.extra-build-features == '' && env.UPLOAD_ARTIFACT == 'true'
        uses: softprops/action-gh-release@v1
        with:
          prerelease: true
          tag_name: ${{ env.TAG_NAME }}
          files: |
            /opt/artifacts/rpm/*.rpm

  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: false
      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: rustdesk-org/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
            # rpm package
            pushd /workspace
            case ${{ matrix.job.arch }} in
              armv7)
                sed -i "s/64bit/32bit/g" ./res/rpm-flutter.spec
                ;;
            esac
            HBB=`pwd` rpmbuild ./res/rpm-flutter.spec -bb
            pushd ~/rpmbuild/RPMS/${{ matrix.job.arch }}
            mkdir -p /opt/artifacts/rpm
            for name in rustdesk*??.rpm; do
                mv "$name" "/opt/artifacts/rpm/${name%%.rpm}.rpm" 
            done
            # rpm suse package
            pushd /workspace
            case ${{ matrix.job.arch }} in
              armv7)
                sed -i "s/64bit/32bit/g" ./res/rpm-flutter-suse.spec
                ;;
            esac
            HBB=`pwd` rpmbuild ./res/rpm-flutter-suse.spec -bb
            pushd ~/rpmbuild/RPMS/${{ matrix.job.arch }}
            mkdir -p /opt/artifacts/rpm
            for name in rustdesk*??.rpm; do
                mv "$name" "/opt/artifacts/rpm/${name%%.rpm}-suse.rpm" 
            done

      - name: Rename rustdesk
        shell: bash
        run: |
          for name in rustdesk*??.deb; do
              # use cp to duplicate deb files to fit other packages.
              cp "$name" "${name%%.deb}-${{ matrix.job.arch }}.deb"
          done

      - name: Publish debian package
        if: matrix.job.extra-build-features == '' && env.UPLOAD_ARTIFACT == 'true'
        uses: softprops/action-gh-release@v1
        with:
          prerelease: true
          tag_name: ${{ env.TAG_NAME }}
          files: |
            rustdesk-${{ env.VERSION }}-${{ matrix.job.arch }}.deb

      - name: Upload Artifact
        uses: actions/upload-artifact@master
        if: ${{ contains(matrix.job.extra-build-features, 'flatpak') }}
        with:
          name: rustdesk-${{ env.VERSION }}-${{ matrix.job.arch }}.deb
          path: rustdesk-${{ env.VERSION }}-${{ matrix.job.arch }}.deb

      - name: Patch archlinux PKGBUILD
        if: ${{ matrix.job.extra-build-features == '' }}
        run: |
          sed -i "s/arch=('x86_64')/arch=('${{ matrix.job.arch }}')/g" res/PKGBUILD

      - name: Build archlinux package
        if: ${{ matrix.job.extra-build-features == '' }}
        uses: vufa/arch-makepkg-action@master
        with:
          packages: >
            llvm
            clang
            libva
            libvdpau
            rust
            gstreamer
            unzip
            git
            cmake
            gcc
            curl
            wget
            yasm
            nasm
            zip
            make
            pkg-config
            clang
            gtk3
            xdotool
            libxcb
            libxfixes
            alsa-lib
            pipewire
            python
            ttf-arphic-uming
            libappindicator-gtk3
            pam
            gst-plugins-base
            gst-plugin-pipewire
          scripts: |
            cd res && HBB=`pwd`/.. FLUTTER=1 makepkg -f

      - name: Publish archlinux package
        if: matrix.job.extra-build-features == '' && env.UPLOAD_ARTIFACT == 'true'
        uses: softprops/action-gh-release@v1
        with:
          prerelease: true
          tag_name: ${{ env.TAG_NAME }}
          files: |
            res/rustdesk*.zst

      - name: Build appimage package
        if: matrix.job.extra-build-features == 'appimage' && env.UPLOAD_ARTIFACT == 'true'
        shell: bash
        run: |
          # set-up appimage-builder
          pushd /tmp
          wget -O appimage-builder-x86_64.AppImage https://github.com/AppImageCrafters/appimage-builder/releases/download/v1.1.0/appimage-builder-1.1.0-x86_64.AppImage
          chmod +x appimage-builder-x86_64.AppImage
          sudo mv appimage-builder-x86_64.AppImage /usr/local/bin/appimage-builder
          popd
          # run appimage-builder
          pushd appimage
          sudo appimage-builder --skip-tests --recipe ./AppImageBuilder-x86_64.yml

      - name: Publish appimage package
        if: matrix.job.extra-build-features == 'appimage' && env.UPLOAD_ARTIFACT == 'true'
        uses: softprops/action-gh-release@v1
        with:
          prerelease: true
          tag_name: ${{ env.TAG_NAME }}
          files: |
            ./appimage/rustdesk-${{ env.VERSION }}-*.AppImage

      - name: Publish fedora package
        if: matrix.job.extra-build-features == '' && env.UPLOAD_ARTIFACT == 'true'
        uses: softprops/action-gh-release@v1
        with:
          prerelease: true
          tag_name: ${{ env.TAG_NAME }}
          files: |
            /opt/artifacts/rpm/*.rpm

  # Temporary disable flatpak arm build
  #
  # build-flatpak-arm:
  #   name: Build Flatpak
  #   needs: [build-rustdesk-linux-arm]
  #   runs-on: ${{ matrix.job.os }}
  #   strategy:
  #     fail-fast: false
  #     matrix:
  #       job:
  #         # - { target: aarch64-unknown-linux-gnu   , os: ubuntu-18.04, arch: arm64 }
  #         - { target: aarch64-unknown-linux-gnu, os: ubuntu-20.04, arch: arm64  }
  #   steps:
  #     - name: Checkout source code
  #       uses: actions/checkout@v3

  #     - name: Download Binary
  #       uses: actions/download-artifact@master
  #       with:
  #         name: rustdesk-${{ env.VERSION }}-${{ matrix.job.target }}-${{ matrix.job.os }}.deb
  #         path: .

  #     - name: Rename Binary
  #       run: |
  #         mv rustdesk-${{ env.VERSION }}-${{ matrix.job.target }}-${{ matrix.job.os }}.deb rustdesk-${{ env.VERSION }}.deb

  #     - uses: rustdesk-org/run-on-arch-action@amd64-support
  #       name: Build rustdesk flatpak package for ${{ matrix.job.arch }}
  #       id: rpm
  #       with:
  #         arch: ${{ matrix.job.arch }}
  #         distro: ubuntu18.04
  #         githubToken: ${{ github.token }}
  #         setup: |
  #           ls -l "${PWD}"
  #         dockerRunArgs: |
  #           --volume "${PWD}:/workspace"
  #         shell: /bin/bash
  #         install: |
  #           apt update -y
  #           apt install -y rpm
  #         run: |
  #           pushd /workspace
  #           # install
  #           apt update -y
  #           apt install -y flatpak flatpak-builder cmake g++ gcc git curl wget nasm yasm libgtk-3-dev git
  #           # flatpak deps
  #           flatpak --user remote-add --if-not-exists flathub https://flathub.org/repo/flathub.flatpakrepo
  #           flatpak --user install -y flathub org.freedesktop.Platform/${{ matrix.job.arch }}/21.08
  #           flatpak --user install -y flathub org.freedesktop.Sdk/${{ matrix.job.arch }}/21.08
  #           # package
  #           pushd flatpak
  #           git clone https://github.com/flathub/shared-modules.git --depth=1
  #           flatpak-builder --user --force-clean --repo=repo ./build ./rustdesk.json
  #           flatpak build-bundle ./repo rustdesk-${{ env.VERSION }}-${{ matrix.job.target }}.flatpak org.rustdesk.rustdesk

  #     - name: Publish flatpak package
  #       uses: softprops/action-gh-release@v1
  #       with:
  #         prerelease: true
  #         tag_name: ${{ env.TAG_NAME }}
  #         files: |
  #           flatpak/rustdesk-${{ env.VERSION }}-${{ matrix.job.target }}.flatpak

  build-flatpak-amd64:
    name: Build Flatpak
    needs: [build-rustdesk-linux-amd64]
    runs-on: ubuntu-20.04
    strategy:
      fail-fast: false
      matrix:
        job:
          - { target: x86_64-unknown-linux-gnu, os: ubuntu-18.04, arch: x86_64 }
    steps:
      - name: Checkout source code
        uses: actions/checkout@v3

      - name: Download Binary
        uses: actions/download-artifact@master
        with:
          name: rustdesk-${{ env.VERSION }}-${{ matrix.job.arch }}.deb
          path: .

      - name: Rename Binary
        run: |
          mv rustdesk-${{ env.VERSION }}-${{ matrix.job.arch }}.deb rustdesk-${{ env.VERSION }}.deb

      - uses: rustdesk-org/run-on-arch-action@amd64-support
        name: Build rustdesk flatpak package for ${{ matrix.job.arch }}
        id: rpm
        with:
          arch: ${{ matrix.job.arch }}
          distro: ubuntu18.04
          githubToken: ${{ github.token }}
          setup: |
            ls -l "${PWD}"
          dockerRunArgs: |
            --volume "${PWD}:/workspace"
          shell: /bin/bash
          install: |
            apt update -y
            apt install -y rpm git wget curl
          run: |
            # disable git safe.directory
            git config --global --add safe.directory "*"
            pushd /workspace
            # install 
            apt update -y
            apt install -y flatpak flatpak-builder cmake g++ gcc git curl wget nasm yasm libgtk-3-dev git
            # flatpak deps
            flatpak --user remote-add --if-not-exists flathub https://flathub.org/repo/flathub.flatpakrepo
            flatpak --user install -y flathub org.freedesktop.Platform/${{ matrix.job.arch }}/21.08
            flatpak --user install -y flathub org.freedesktop.Sdk/${{ matrix.job.arch }}/21.08
            # package
            pushd flatpak
            git clone https://github.com/flathub/shared-modules.git --depth=1
            flatpak-builder --user --force-clean --repo=repo ./build ./rustdesk.json
            flatpak build-bundle ./repo rustdesk-${{ env.VERSION }}-${{ matrix.job.arch }}.flatpak com.rustdesk.RustDesk

      - name: Publish flatpak package
        uses: softprops/action-gh-release@v1
        if: env.UPLOAD_ARTIFACT == 'true'
        with:
          prerelease: true
          tag_name: ${{ env.TAG_NAME }}
          files: |
            flatpak/rustdesk-${{ env.VERSION }}-${{ matrix.job.arch }}.flatpak
