Files
rustdesk/.gitea/workflows/build-macos.yml
mike 47f0d0fff2
build-linux / build-linux-x64 (push) Successful in 5m23s
build-macos / build-macos-x64 (push) Successful in 9m4s
build-windows / build-windows-x64 (push) Successful in 10m13s
Implement CI workflow for Gitea. Include provision scripts for Gitea runners.
2026-05-07 09:39:23 +02:00

232 lines
10 KiB
YAML

name: build-macos
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.81" # MAC_RUST_VERSION upstream (cidre needs >=1.81)
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-macos-x64
# Intel Mac runner. provision.sh tags x86_64 macOS hosts with the X64 label.
runs-on: [self-hosted, macOS, X64]
timeout-minutes: 240
env:
VCPKG_ROOT: /opt/vcpkg
VCPKG_BINARY_SOURCES: "clear;files,/var/cache/vcpkg,readwrite"
VCPKG_DEFAULT_TRIPLET: x64-osx
VCPKG_DEFAULT_HOST_TRIPLET: x64-osx
steps:
- name: Checkout source
uses: actions/checkout@v4
with:
submodules: recursive
- name: Verify host toolchain
shell: bash
run: |
required=(git bash python3 rustc cargo rustup clang flutter cmake ninja nasm pkg-config create-dmg)
missing=()
for t in "${required[@]}"; do
if command -v "$t" >/dev/null 2>&1; then
printf '%-15s %s\n' "$t" "$(command -v "$t")"
else
missing+=("$t")
printf '%-15s 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; }
- 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 "Display : $display"
echo "VERSION_DISPLAY=$display" >> "$GITHUB_ENV"
- name: Patch Cargo.toml with display version
shell: bash
run: |
# BSD sed (macOS): -i requires an empty backup-suffix arg.
sed -i '' -E "1,/^version[[:space:]]*=/{s/^version[[:space:]]*=[[:space:]]*\"${VERSION_BASE}\"/version = \"${VERSION_DISPLAY}\"/;}" Cargo.toml
grep '^version' Cargo.toml | head -1
# No deployment-target patch on x86_64: build.py's build_flutter_dmg()
# already exports MACOSX_DEPLOYMENT_TARGET=10.14 internally, matching the
# Flutter Xcode project. Upstream only patches the target for arm64
# (which needs 12.3+).
- name: Ensure Rust toolchain configured
shell: bash
run: |
rustup toolchain install "$RUST_VERSION" --profile minimal --component rustfmt
rustup default "$RUST_VERSION"
rustup target add x86_64-apple-darwin
rustc --version
cargo --version
- name: Install flutter_rust_bridge codegen tools
shell: bash
run: |
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
# Same dual-SDK trick as Linux: bridge codegen 1.80.1 produces broken
# Dart on Flutter 3.24.5; provision.sh installs 3.22.3 at
# /opt/flutter-bridge for codegen only. Switch back to 3.24.5 after.
export PATH="/opt/cargo-tools/bin:/opt/flutter-bridge/bin:$PATH"
flutter --version
command -v flutter_rust_bridge_codegen
# Match the Linux fix: don't pass --llvm-path, let ffigen find Xcode
# CLT's libclang via system defaults. Passing brew's llvm or a custom
# libclang path triggered fr_bridge_codegen 1.80.1's bad-emission bug
# (stray `typedef bool = NativeFunction<...>`) on Linux; same logic
# carries over here.
unset LIBCLANG_PATH
(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 \
--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
(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 " 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)"
- name: vcpkg install dependencies (x64-osx)
shell: bash
run: |
mkdir -p /var/cache/vcpkg
if ! "$VCPKG_ROOT/vcpkg" install \
--triplet x64-osx \
--x-install-root="$VCPKG_ROOT/installed"; then
find "$VCPKG_ROOT/" -name '*.log' -exec sh -c 'echo "===== {} ====="; cat "{}"' \;
exit 1
fi
- name: Build RustDesk (.app + .dmg)
shell: bash
run: |
set -e
# build.py -> build_flutter_dmg() does:
# - MACOSX_DEPLOYMENT_TARGET=10.14 cargo build --features <features> --release
# - cp liblibrustdesk.dylib librustdesk.dylib
# - flutter build macos --release
# - cp -rf ../target/release/service .../RustDesk.app/Contents/MacOS/
# It does NOT package the .dmg (the create-dmg call is commented out).
# We package below.
#
# No --screencapturekit on x86_64: upstream's matrix only enables it
# on aarch64 (cidre's ScreenCaptureKit bindings target arm64-only APIs).
python3 build.py --flutter --hwcodec --unix-file-copy-paste
# Ad-hoc re-sign the whole bundle in one pass.
# `flutter build macos --release` ad-hoc signs the main binary, but
# FlutterMacOS.framework already carries its own ad-hoc signature
# from Flutter's engine artifacts. dyld on Apple Silicon (macOS 13+)
# enforces Team ID match between the main process and every loaded
# framework -- two ad-hoc signatures from different signing passes
# have different per-binary cdhashes and fail the check, producing
# `mapping process and mapped file have different Team IDs` at
# launch time on M-series Macs. `codesign --deep --sign -` re-signs
# every nested binary/framework/dylib with the same ad-hoc identity
# in one pass, so all components share a consistent signing context.
# When we wire up real Developer ID + notarization later, replace
# `-` with the cert identity and drop --deep in favor of inside-out
# signing.
codesign --force --deep --sign - \
./flutter/build/macos/Build/Products/Release/RustDesk.app
codesign --verify --deep --strict --verbose=2 \
./flutter/build/macos/Build/Products/Release/RustDesk.app
mkdir -p ./SignOutput
# Use hdiutil (not create-dmg) because the runner is a LaunchDaemon
# with no GUI/Finder session. create-dmg drives Finder via AppleScript
# for icon layout and fails with `-10810` in daemon context. hdiutil
# produces a fully functional compressed DMG with no GUI calls.
dmg_staging="$(mktemp -d -t rustdesk-dmg)"
cp -R ./flutter/build/macos/Build/Products/Release/RustDesk.app "$dmg_staging/"
ln -s /Applications "$dmg_staging/Applications"
hdiutil create \
-volname "RustDesk" \
-srcfolder "$dmg_staging" \
-ov \
-format UDZO \
"./SignOutput/rustdesk-${VERSION_DISPLAY}-x86_64.dmg"
rm -rf "$dmg_staging"
- name: Report signing status of build artifacts
shell: bash
run: |
for f in ./SignOutput/*.dmg; do
[[ -f "$f" ]] || continue
size=$(stat -f%z "$f")
sig=$(codesign -dv "$f" 2>&1 | grep -E '^Authority' | head -1 || true)
if [[ -z "$sig" ]]; then
printf '[UNSIGNED] %s (%d bytes)\n' "$(basename "$f")" "$size"
else
printf '[ SIGNED ] %s (%d bytes) %s\n' "$(basename "$f")" "$size" "$sig"
fi
done
echo "::warning title=Unsigned .dmg::Wire up codesign + notarytool before distributing."
- name: Upload artifacts
uses: actions/upload-artifact@v3
with:
name: rustdesk-macos-x64-${{ github.sha }}
path: SignOutput/rustdesk-*.dmg
if-no-files-found: warn
retention-days: 14