name: build-linux on: push: branches: [pro-features] workflow_dispatch: inputs: version_suffix: description: "Version suffix (e.g. 'cst', 'beta1'). Empty = vanilla." type: string default: "cst" env: RUST_VERSION: "1.75" LLVM_VERSION: "15.0.6" # Where provision.sh installs LLVM (binary tarball from llvm.org). Same exact # version as the Windows runner uses, distro-portable. LLVM_HOME: '/opt/llvm-15.0.6' FLUTTER_VERSION: "3.24.5" VCPKG_COMMIT_ID: "120deac3062162151622ca4860575a33844ba10b" CARGO_EXPAND_VERSION: "1.0.95" FLUTTER_RUST_BRIDGE_VERSION: "1.80.1" VERSION_BASE: "1.4.6" VERSION_SUFFIX: ${{ inputs.version_suffix || 'cst' }} jobs: build-x64: name: build-linux-x64 # Pinned to ubuntu-22.04 because flutter_rust_bridge_codegen 1.80.1 emits # broken Dart on Debian 13 (matches upstream rustdesk's bridge.yml host). # provision.sh tags Ubuntu 22.04 hosts with the `ubuntu-22.04` label. runs-on: [self-hosted, Linux, X64, ubuntu-22.04] timeout-minutes: 240 env: VCPKG_ROOT: /opt/vcpkg VCPKG_BINARY_SOURCES: "clear;files,/var/cache/vcpkg,readwrite" LIBCLANG_PATH: /opt/llvm-15.0.6/lib steps: - name: Checkout source uses: actions/checkout@v4 with: submodules: recursive - name: Verify host toolchain shell: bash run: | required=(node git bash python3 rustc cargo rustup clang flutter cmake ninja nasm pkg-config dpkg-deb) missing=() for t in "${required[@]}"; do if command -v "$t" >/dev/null 2>&1; then printf '%-20s %s\n' "$t" "$(command -v "$t")" else missing+=("$t") printf '%-20s MISSING\n' "$t" fi done if [[ ${#missing[@]} -gt 0 ]]; then echo "Missing tools: ${missing[*]}. Re-run provision.sh on the runner host." exit 1 fi [[ -d "$VCPKG_ROOT" && -x "$VCPKG_ROOT/vcpkg" ]] || { echo "VCPKG_ROOT=$VCPKG_ROOT invalid"; exit 1; } [[ -f "$LIBCLANG_PATH/libclang.so" ]] || { echo "libclang.so not found at $LIBCLANG_PATH"; exit 1; } - name: Compute version strings shell: bash run: | base="${VERSION_BASE}" suffix="${VERSION_SUFFIX}" [[ "$base" =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]] || { echo "VERSION_BASE '$base' must be major.minor.patch"; exit 1; } if [[ -n "$suffix" ]]; then display="${base}-${suffix}"; else display="${base}"; fi echo "Base : $base" echo "Suffix : $suffix" echo "Display : $display" echo "VERSION_DISPLAY=$display" >> "$GITHUB_ENV" - name: Patch Cargo.toml with display version shell: bash run: | sed -i -E "0,/^version[[:space:]]*=/{s/^version[[:space:]]*=[[:space:]]*\"${VERSION_BASE}\"/version = \"${VERSION_DISPLAY}\"/}" Cargo.toml grep '^version' Cargo.toml | head -1 - name: Ensure Rust toolchain configured shell: bash run: | # provision.sh installs Rust machine-wide at /opt/cargo + /opt/rustup, # so this is normally a no-op verification. Kept as a guardrail. rustup toolchain install "$RUST_VERSION" --profile minimal --component rustfmt rustup default "$RUST_VERSION" rustup target add x86_64-unknown-linux-gnu rustc --version cargo --version - name: Install flutter_rust_bridge codegen tools shell: bash run: | # Pin install destination so binaries land in a deterministic path # regardless of CARGO_HOME. tools=/opt/cargo-tools mkdir -p "$tools/bin" cargo install --root "$tools" cargo-expand --version "$CARGO_EXPAND_VERSION" --locked cargo install --root "$tools" flutter_rust_bridge_codegen --version "$FLUTTER_RUST_BRIDGE_VERSION" --features uuid --locked ls -la "$tools/bin" [[ -x "$tools/bin/flutter_rust_bridge_codegen" ]] || { echo "missing fr_bridge_codegen"; exit 1; } echo "$tools/bin" >> "$GITHUB_PATH" - name: Generate Rust <-> Dart bridge (with Flutter 3.22.3) shell: bash run: | set -e # flutter_rust_bridge_codegen 1.80.1 + freezed produces broken Dart # output (wrong FFI types, unprefixed Int/Pointer in part files) when # run under Flutter 3.24.5 on Linux. Upstream's bridge.yml works around # this by running the bridge generation under Flutter 3.22.3 -- the # produced .dart/.freezed.dart files are then compatible with the # 3.24.5 build that follows. # # provision.sh installs Flutter 3.22.3 at /opt/flutter-bridge alongside # /opt/flutter (3.24.5). Use the bridge SDK ONLY for pub get + codegen, # then unset PATH overrides so subsequent steps use the build SDK. export PATH="/opt/cargo-tools/bin:/opt/flutter-bridge/bin:$PATH" flutter --version command -v flutter_rust_bridge_codegen # CRITICAL: use the apt-installed libclang (libclang-dev), NOT the # LLVM 15.0.6 tarball at /opt/llvm-15.0.6 that the rest of the build # uses. fr_bridge_codegen 1.80.1 emits broken Dart (stray # `typedef bool = NativeFunction<...>`, unprefixed Int/Pointer in # part files) when its internal ffigen runs against the tarball # libclang. Upstream bridge.yml uses apt's libclang and the same # codegen produces clean output. Don't pass --llvm-path either; let # ffigen find libclang via system defaults. unset LIBCLANG_PATH # extended_text 14.0.0 requires Dart >=3.5 (Flutter 3.24+). Flutter # 3.22.3 has Dart 3.4.4, so downgrade to 13.0.0 for the duration of # bridge generation. Mirrors upstream bridge.yml. (cd flutter && sed -i -e 's/extended_text: 14.0.0/extended_text: 13.0.0/g' pubspec.yaml) (cd flutter && flutter pub get) # flutter_rust_bridge_codegen invokes `flutter pub run ffigen` # internally, which re-validates pubspec.yaml -- so pubspec.yaml must # still be the downgraded version when this runs. 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 cp ./flutter/macos/Runner/bridge_generated.h ./flutter/ios/Runner/bridge_generated.h # Now bridge gen is done. Restore the original pubspec.yaml and # re-resolve under the build SDK (3.24.5) so pubspec.lock has the # correct entries for the final flutter build linux step. (cd flutter && git checkout -- pubspec.yaml) (cd flutter && /opt/flutter/bin/flutter pub get) - name: Diagnose generated bridge files shell: bash run: | set +e echo "============================================================" echo " generated_bridge.dart (first 80 lines)" echo "============================================================" head -80 flutter/lib/generated_bridge.dart 2>/dev/null || echo "(missing)" echo echo "============================================================" echo " generated_bridge.freezed.dart (first 80 lines)" echo "============================================================" head -80 flutter/lib/generated_bridge.freezed.dart 2>/dev/null || echo "(missing)" echo echo "============================================================" echo " Search: typedef declarations that might shadow bool/Int/Pointer" echo "============================================================" grep -nE 'typedef (bool|Int|Pointer|Bool)' \ flutter/lib/generated_bridge.dart \ flutter/lib/generated_bridge.freezed.dart 2>/dev/null || echo "(no shadowing typedefs)" echo echo "============================================================" echo " Search: imports that might pull weird symbols" echo "============================================================" grep -nE '^import|^export|^part ' \ flutter/lib/generated_bridge.dart \ flutter/lib/generated_bridge.freezed.dart 2>/dev/null echo echo "============================================================" echo " store_dart_post_cobject signature in generated_bridge.dart" echo "============================================================" grep -nA2 'store_dart_post_cobject' flutter/lib/generated_bridge.dart 2>/dev/null | head -30 echo echo "============================================================" echo " Line 25 of generated_bridge.freezed.dart (the failing one)" echo "============================================================" sed -n '20,30p' flutter/lib/generated_bridge.freezed.dart 2>/dev/null echo echo "============================================================" echo " flutter_rust_bridge package version actually resolved" echo "============================================================" grep -A2 'flutter_rust_bridge:' flutter/pubspec.lock | head -10 - name: vcpkg install dependencies (x64-linux) shell: bash env: VCPKG_DEFAULT_HOST_TRIPLET: x64-linux run: | mkdir -p /var/cache/vcpkg if ! "$VCPKG_ROOT/vcpkg" install \ --triplet x64-linux \ --x-install-root="$VCPKG_ROOT/installed"; then find "$VCPKG_ROOT/" -name '*.log' -exec sh -c 'echo "===== {} ====="; cat "{}"' \; exit 1 fi - name: Build RustDesk (.deb) shell: bash run: | set -e # build.py on Linux (no pacman/yum/zypper detected) goes to # build_flutter_deb() which does: # - cargo build --features --lib --release # - flutter build linux --release # - assembles tmpdeb/ and runs dpkg-deb -b # Output: ./rustdesk-.deb in the repo root. python3 build.py --flutter --hwcodec --unix-file-copy-paste mkdir -p ./SignOutput # build.py names the .deb after Cargo.toml's version which we patched # above, so the file should already carry $VERSION_DISPLAY. mv "./rustdesk-${VERSION_DISPLAY}.deb" "./SignOutput/rustdesk-${VERSION_DISPLAY}-amd64.deb" - name: Report signing status of build artifacts shell: bash run: | # .deb files are typically signed with debsign or via the apt repo # signing pipeline, not the .deb itself. Just list contents for now. for f in ./SignOutput/*.deb; do [[ -f "$f" ]] || continue size=$(stat -c%s "$f") printf '[UNSIGNED] %s (%d bytes)\n' "$(basename "$f")" "$size" done # Gitea/GHA-style annotation so it surfaces in the run summary. echo "::warning title=Unsigned .deb::Wire up debsigs / repo signing before distributing." - name: Upload artifacts uses: actions/upload-artifact@v3 with: name: rustdesk-linux-x64-${{ github.sha }} path: SignOutput/rustdesk-*.deb if-no-files-found: warn retention-days: 14