661 lines
17 KiB
YAML
661 lines
17 KiB
YAML
name: RustDesk Windows x64
|
|
|
|
on:
|
|
workflow_dispatch:
|
|
|
|
env:
|
|
RUSTDESK_VERSION: "1.4.9"
|
|
|
|
jobs:
|
|
generate-bridge:
|
|
name: Generate Flutter Rust Bridge
|
|
runs-on: rustdesk-android
|
|
|
|
steps:
|
|
- name: Clone RustDesk 1.4.9
|
|
shell: bash
|
|
run: |
|
|
set -euxo pipefail
|
|
|
|
rm -rf rustdesk bridge-artifact
|
|
|
|
git clone \
|
|
--branch "${RUSTDESK_VERSION}" \
|
|
--depth 1 \
|
|
https://github.com/rustdesk/rustdesk.git \
|
|
rustdesk
|
|
|
|
git -C rustdesk submodule update \
|
|
--init \
|
|
--recursive
|
|
|
|
- name: Generate bridge with Flutter 3.22.3
|
|
shell: bash
|
|
run: |
|
|
set -euxo pipefail
|
|
|
|
export PATH="/opt/flutter-3.22.3/bin:/opt/rust/cargo/bin:${PATH}"
|
|
|
|
flutter --version
|
|
rustc --version
|
|
flutter_rust_bridge_codegen --version
|
|
|
|
cd rustdesk
|
|
|
|
# RustDesk 1.4.9 bridge is generated with Flutter 3.22.3.
|
|
# extended_text 14 requires newer Dart, therefore upstream
|
|
# temporarily uses 13.0.0 for bridge generation.
|
|
sed -i \
|
|
's/extended_text: 14.0.0/extended_text: 13.0.0/g' \
|
|
flutter/pubspec.yaml
|
|
|
|
rm -rf flutter/.dart_tool
|
|
|
|
pushd flutter
|
|
flutter pub get
|
|
popd
|
|
|
|
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
|
|
|
|
test -f ./src/bridge_generated.rs
|
|
test -f ./src/bridge_generated.io.rs
|
|
test -f ./flutter/lib/generated_bridge.dart
|
|
test -f ./flutter/lib/generated_bridge.freezed.dart
|
|
|
|
- name: Prepare bridge artifact
|
|
shell: bash
|
|
run: |
|
|
set -euxo pipefail
|
|
|
|
rm -rf bridge-artifact
|
|
|
|
mkdir -p bridge-artifact/src
|
|
mkdir -p bridge-artifact/flutter/lib
|
|
mkdir -p bridge-artifact/flutter/macos/Runner
|
|
mkdir -p bridge-artifact/flutter/ios/Runner
|
|
|
|
cp rustdesk/src/bridge_generated.rs \
|
|
bridge-artifact/src/
|
|
|
|
cp rustdesk/src/bridge_generated.io.rs \
|
|
bridge-artifact/src/
|
|
|
|
cp rustdesk/flutter/lib/generated_bridge.dart \
|
|
bridge-artifact/flutter/lib/
|
|
|
|
cp rustdesk/flutter/lib/generated_bridge.freezed.dart \
|
|
bridge-artifact/flutter/lib/
|
|
|
|
cp rustdesk/flutter/macos/Runner/bridge_generated.h \
|
|
bridge-artifact/flutter/macos/Runner/
|
|
|
|
cp rustdesk/flutter/ios/Runner/bridge_generated.h \
|
|
bridge-artifact/flutter/ios/Runner/
|
|
|
|
- name: Upload bridge artifact
|
|
uses: https://github.com/actions/upload-artifact@v7
|
|
with:
|
|
name: rustdesk-bridge-1.4.9
|
|
path: bridge-artifact/
|
|
if-no-files-found: error
|
|
retention-days: 7
|
|
|
|
|
|
build-windows:
|
|
name: Build Windows x64
|
|
needs:
|
|
- generate-bridge
|
|
|
|
runs-on: rustdesk-windows
|
|
|
|
env:
|
|
RUSTUP_HOME: C:\BuildTools\rustup
|
|
CARGO_HOME: C:\BuildTools\cargo
|
|
FLUTTER_ROOT: C:\BuildTools\flutter-3.24.5
|
|
PUB_CACHE: C:\BuildTools\pub-cache
|
|
LIBCLANG_PATH: C:\Program Files\LLVM\bin
|
|
VCPKG_ROOT: C:\vcpkg
|
|
|
|
steps:
|
|
- name: Validate Windows builder
|
|
shell: pwsh
|
|
run: |
|
|
$ErrorActionPreference = "Stop"
|
|
|
|
Write-Host "===== Runner user ====="
|
|
whoami
|
|
|
|
Write-Host "`n===== Rust ====="
|
|
rustc --version
|
|
cargo --version
|
|
rustfmt --version
|
|
|
|
Write-Host "`n===== Flutter ====="
|
|
flutter --version
|
|
|
|
Write-Host "`n===== LLVM ====="
|
|
clang --version
|
|
|
|
Write-Host "`n===== Python ====="
|
|
python --version
|
|
|
|
Write-Host "`n===== NASM ====="
|
|
nasm -v
|
|
|
|
Write-Host "`n===== vcpkg ====="
|
|
vcpkg version
|
|
|
|
if (-not (Test-Path "$env:LIBCLANG_PATH\libclang.dll")) {
|
|
throw "libclang.dll not found"
|
|
}
|
|
|
|
if (-not (Test-Path "$env:FLUTTER_ROOT\bin\flutter.bat")) {
|
|
throw "Flutter not found"
|
|
}
|
|
|
|
if (-not (Test-Path "$env:VCPKG_ROOT\vcpkg.exe")) {
|
|
throw "vcpkg not found"
|
|
}
|
|
|
|
$target = rustup target list --installed
|
|
|
|
if ($target -notcontains "x86_64-pc-windows-msvc") {
|
|
throw "x86_64-pc-windows-msvc Rust target missing"
|
|
}
|
|
|
|
$flutterPatch = git `
|
|
-C "$env:FLUTTER_ROOT" `
|
|
status --short
|
|
|
|
if ($flutterPatch -notmatch "dropdown_menu.dart") {
|
|
throw "RustDesk Flutter patch is missing"
|
|
}
|
|
|
|
$engine = Join-Path `
|
|
$env:FLUTTER_ROOT `
|
|
"bin\cache\artifacts\engine\windows-x64-release"
|
|
|
|
foreach ($file in @(
|
|
"flutter_windows.dll",
|
|
"flutter_windows.dll.lib",
|
|
"gen_snapshot.exe"
|
|
)) {
|
|
if (-not (Test-Path (Join-Path $engine $file))) {
|
|
throw "Missing RustDesk custom Flutter engine file: $file"
|
|
}
|
|
}
|
|
|
|
Write-Host "Windows build environment OK"
|
|
|
|
- name: Clone RustDesk 1.4.9
|
|
shell: pwsh
|
|
run: |
|
|
$ErrorActionPreference = "Stop"
|
|
|
|
Remove-Item `
|
|
".\rustdesk" `
|
|
-Recurse `
|
|
-Force `
|
|
-ErrorAction SilentlyContinue
|
|
|
|
git -c core.longpaths=true clone `
|
|
--branch "$env:RUSTDESK_VERSION" `
|
|
--depth 1 `
|
|
https://github.com/rustdesk/rustdesk.git `
|
|
rustdesk
|
|
|
|
if ($LASTEXITCODE -ne 0) {
|
|
throw "RustDesk clone failed"
|
|
}
|
|
|
|
git `
|
|
-C rustdesk `
|
|
-c core.longpaths=true `
|
|
submodule update `
|
|
--init `
|
|
--recursive
|
|
|
|
if ($LASTEXITCODE -ne 0) {
|
|
throw "RustDesk submodule checkout failed"
|
|
}
|
|
|
|
- name: Restore generated bridge
|
|
uses: https://github.com/actions/download-artifact@v8
|
|
with:
|
|
name: rustdesk-bridge-1.4.9
|
|
path: rustdesk
|
|
|
|
- name: Verify bridge
|
|
shell: pwsh
|
|
run: |
|
|
$ErrorActionPreference = "Stop"
|
|
|
|
$files = @(
|
|
"rustdesk\src\bridge_generated.rs",
|
|
"rustdesk\src\bridge_generated.io.rs",
|
|
"rustdesk\flutter\lib\generated_bridge.dart",
|
|
"rustdesk\flutter\lib\generated_bridge.freezed.dart"
|
|
)
|
|
|
|
foreach ($file in $files) {
|
|
if (-not (Test-Path $file)) {
|
|
throw "Missing bridge file: $file"
|
|
}
|
|
|
|
Write-Host "$file OK"
|
|
}
|
|
|
|
- name: Patch RustDesk server configuration
|
|
shell: pwsh
|
|
env:
|
|
ID_SERVER: ${{ secrets.RUSTDESK_ID_SERVER }}
|
|
PUB_KEY: ${{ secrets.RUSTDESK_KEY }}
|
|
run: |
|
|
$ErrorActionPreference = "Stop"
|
|
|
|
if ([string]::IsNullOrWhiteSpace($env:ID_SERVER)) {
|
|
throw "RUSTDESK_ID_SERVER secret is empty"
|
|
}
|
|
|
|
if ([string]::IsNullOrWhiteSpace($env:PUB_KEY)) {
|
|
throw "RUSTDESK_KEY secret is empty"
|
|
}
|
|
|
|
@'
|
|
import json
|
|
import os
|
|
import re
|
|
from pathlib import Path
|
|
|
|
path = Path(r"rustdesk/libs/hbb_common/src/config.rs")
|
|
|
|
if not path.exists():
|
|
raise SystemExit(f"config.rs not found: {path}")
|
|
|
|
server = os.environ["ID_SERVER"].strip()
|
|
key = os.environ["PUB_KEY"].strip()
|
|
|
|
text = path.read_text(encoding="utf-8")
|
|
|
|
rendezvous_pattern = (
|
|
r"pub const RENDEZVOUS_SERVERS\s*:\s*[^=]+?="
|
|
r"\s*&\[(?:.|\n)*?\];"
|
|
)
|
|
|
|
rendezvous_replacement = (
|
|
"pub const RENDEZVOUS_SERVERS: &[&str] = &["
|
|
+ json.dumps(server)
|
|
+ "];"
|
|
)
|
|
|
|
text, rendezvous_count = re.subn(
|
|
rendezvous_pattern,
|
|
rendezvous_replacement,
|
|
text,
|
|
count=1,
|
|
)
|
|
|
|
key_pattern = (
|
|
r"pub const RS_PUB_KEY\s*:\s*[^=]+?="
|
|
r"\s*.*?;"
|
|
)
|
|
|
|
key_replacement = (
|
|
"pub const RS_PUB_KEY: &str = "
|
|
+ json.dumps(key)
|
|
+ ";"
|
|
)
|
|
|
|
text, key_count = re.subn(
|
|
key_pattern,
|
|
key_replacement,
|
|
text,
|
|
count=1,
|
|
flags=re.S,
|
|
)
|
|
|
|
if rendezvous_count != 1:
|
|
raise SystemExit(
|
|
f"RENDEZVOUS_SERVERS replacement count: {rendezvous_count}"
|
|
)
|
|
|
|
if key_count != 1:
|
|
raise SystemExit(
|
|
f"RS_PUB_KEY replacement count: {key_count}"
|
|
)
|
|
|
|
path.write_text(text, encoding="utf-8")
|
|
|
|
print("RENDEZVOUS_SERVERS patched")
|
|
print("RS_PUB_KEY patched")
|
|
'@ | python -
|
|
|
|
if ($LASTEXITCODE -ne 0) {
|
|
throw "RustDesk configuration patch failed"
|
|
}
|
|
|
|
- name: Verify pinned vcpkg
|
|
shell: pwsh
|
|
run: |
|
|
$ErrorActionPreference = "Stop"
|
|
|
|
$expected = "120deac3062162151622ca4860575a33844ba10b"
|
|
|
|
$actual = git `
|
|
-C "$env:VCPKG_ROOT" `
|
|
rev-parse HEAD
|
|
|
|
Write-Host "vcpkg commit: $actual"
|
|
|
|
if ($actual -ne $expected) {
|
|
throw "Wrong vcpkg commit: $actual"
|
|
}
|
|
|
|
- name: Install RustDesk vcpkg dependencies
|
|
shell: pwsh
|
|
run: |
|
|
$ErrorActionPreference = "Stop"
|
|
|
|
Set-Location rustdesk
|
|
|
|
$env:VCPKG_DEFAULT_HOST_TRIPLET = "x64-windows-static"
|
|
|
|
& "$env:VCPKG_ROOT\vcpkg.exe" `
|
|
install `
|
|
--triplet x64-windows-static `
|
|
--x-install-root="$env:VCPKG_ROOT\installed"
|
|
|
|
if ($LASTEXITCODE -ne 0) {
|
|
throw "vcpkg install failed"
|
|
}
|
|
|
|
- name: Build RustDesk
|
|
shell: pwsh
|
|
run: |
|
|
$ErrorActionPreference = "Stop"
|
|
|
|
Set-Location rustdesk
|
|
|
|
python `
|
|
.\build.py `
|
|
--portable `
|
|
--flutter `
|
|
--skip-portable-pack `
|
|
--hwcodec `
|
|
--vram
|
|
|
|
if ($LASTEXITCODE -ne 0) {
|
|
throw "RustDesk build failed"
|
|
}
|
|
|
|
$release = `
|
|
".\flutter\build\windows\x64\runner\Release"
|
|
|
|
if (-not (Test-Path "$release\rustdesk.exe")) {
|
|
throw "rustdesk.exe was not produced"
|
|
}
|
|
|
|
$packageDir = ".\dist\rustdesk"
|
|
|
|
Remove-Item `
|
|
$packageDir `
|
|
-Recurse `
|
|
-Force `
|
|
-ErrorAction SilentlyContinue
|
|
|
|
New-Item `
|
|
-ItemType Directory `
|
|
-Force `
|
|
-Path $packageDir | Out-Null
|
|
|
|
Copy-Item `
|
|
"$release\*" `
|
|
"$packageDir\" `
|
|
-Recurse `
|
|
-Force
|
|
|
|
Write-Host "RustDesk main build OK"
|
|
|
|
- name: Build WindowInjection.dll
|
|
shell: pwsh
|
|
run: |
|
|
$ErrorActionPreference = "Stop"
|
|
|
|
Set-Location rustdesk
|
|
|
|
$source = `
|
|
".\third-party\RustDeskTempTopMostWindow"
|
|
|
|
Remove-Item `
|
|
$source `
|
|
-Recurse `
|
|
-Force `
|
|
-ErrorAction SilentlyContinue
|
|
|
|
New-Item `
|
|
-ItemType Directory `
|
|
-Force `
|
|
-Path ".\third-party" | Out-Null
|
|
|
|
git clone `
|
|
https://github.com/rustdesk-org/RustDeskTempTopMostWindow `
|
|
$source
|
|
|
|
if ($LASTEXITCODE -ne 0) {
|
|
throw "RustDeskTempTopMostWindow clone failed"
|
|
}
|
|
|
|
git `
|
|
-C $source `
|
|
checkout `
|
|
ecd8d6a139eee76845ea66423fb739af450fda90
|
|
|
|
if ($LASTEXITCODE -ne 0) {
|
|
throw "RustDeskTempTopMostWindow checkout failed"
|
|
}
|
|
|
|
$vswhere = `
|
|
"${env:ProgramFiles(x86)}\Microsoft Visual Studio\Installer\vswhere.exe"
|
|
|
|
$msbuild = & $vswhere `
|
|
-latest `
|
|
-products * `
|
|
-find "MSBuild\**\Bin\MSBuild.exe" |
|
|
Select-Object -First 1
|
|
|
|
if (-not $msbuild) {
|
|
throw "MSBuild.exe not found"
|
|
}
|
|
|
|
Write-Host "MSBuild: $msbuild"
|
|
|
|
& $msbuild `
|
|
"$source\WindowInjection\WindowInjection.vcxproj" `
|
|
"-p:Configuration=Release" `
|
|
"-p:Platform=x64" `
|
|
"/p:TargetVersion=Windows10"
|
|
|
|
if ($LASTEXITCODE -ne 0) {
|
|
throw "WindowInjection.dll build failed"
|
|
}
|
|
|
|
$dll = `
|
|
"$source\WindowInjection\x64\Release\WindowInjection.dll"
|
|
|
|
if (-not (Test-Path $dll)) {
|
|
throw "WindowInjection.dll not found"
|
|
}
|
|
|
|
Copy-Item `
|
|
$dll `
|
|
".\dist\rustdesk\WindowInjection.dll" `
|
|
-Force
|
|
|
|
- name: Add usbmmidd
|
|
shell: pwsh
|
|
run: |
|
|
$ErrorActionPreference = "Stop"
|
|
|
|
Set-Location rustdesk
|
|
|
|
$zip = ".\third-party\usbmmidd_v2.zip"
|
|
$extract = ".\third-party\usbmmidd"
|
|
|
|
Remove-Item `
|
|
$extract `
|
|
-Recurse `
|
|
-Force `
|
|
-ErrorAction SilentlyContinue
|
|
|
|
Invoke-WebRequest `
|
|
-Uri "https://github.com/rustdesk-org/rdev/releases/download/usbmmidd_v2/usbmmidd_v2.zip" `
|
|
-OutFile $zip
|
|
|
|
Expand-Archive `
|
|
-Path $zip `
|
|
-DestinationPath $extract `
|
|
-Force
|
|
|
|
$usb = Join-Path $extract "usbmmidd_v2"
|
|
|
|
if (-not (Test-Path $usb)) {
|
|
throw "usbmmidd_v2 directory not found"
|
|
}
|
|
|
|
Remove-Item `
|
|
"$usb\Win32" `
|
|
-Recurse `
|
|
-Force `
|
|
-ErrorAction SilentlyContinue
|
|
|
|
foreach ($file in @(
|
|
"deviceinstaller64.exe",
|
|
"deviceinstaller.exe",
|
|
"usbmmidd.bat"
|
|
)) {
|
|
Remove-Item `
|
|
(Join-Path $usb $file) `
|
|
-Force `
|
|
-ErrorAction SilentlyContinue
|
|
}
|
|
|
|
Copy-Item `
|
|
$usb `
|
|
".\dist\rustdesk\usbmmidd_v2" `
|
|
-Recurse `
|
|
-Force
|
|
|
|
- name: Prepare portable packer
|
|
shell: pwsh
|
|
run: |
|
|
$ErrorActionPreference = "Stop"
|
|
|
|
Set-Location rustdesk
|
|
|
|
$runnerRes = Get-ChildItem `
|
|
".\flutter\build\windows\x64" `
|
|
-Filter "Runner.res" `
|
|
-Recurse `
|
|
-ErrorAction SilentlyContinue |
|
|
Select-Object -First 1
|
|
|
|
if ($runnerRes) {
|
|
Write-Host "Runner.res: $($runnerRes.FullName)"
|
|
|
|
Copy-Item `
|
|
$runnerRes.FullName `
|
|
".\libs\portable\Runner.res" `
|
|
-Force
|
|
}
|
|
else {
|
|
Write-Host "Runner.res not found, continuing"
|
|
}
|
|
|
|
# Same manifest adjustment used by upstream before
|
|
# generating the self-extracted portable executable.
|
|
$manifest = ".\res\manifest.xml"
|
|
|
|
$manifestContent = Get-Content $manifest
|
|
|
|
$manifestContent |
|
|
Where-Object { $_ -notmatch "dpiAware" } |
|
|
Set-Content `
|
|
$manifest `
|
|
-Encoding utf8
|
|
|
|
Push-Location ".\libs\portable"
|
|
|
|
try {
|
|
python -m pip install `
|
|
--disable-pip-version-check `
|
|
-r requirements.txt
|
|
|
|
if ($LASTEXITCODE -ne 0) {
|
|
throw "portable requirements installation failed"
|
|
}
|
|
|
|
python `
|
|
.\generate.py `
|
|
-f ..\..\dist\rustdesk\ `
|
|
-o . `
|
|
-e ..\..\dist\rustdesk\rustdesk.exe
|
|
|
|
if ($LASTEXITCODE -ne 0) {
|
|
throw "portable packer generation failed"
|
|
}
|
|
}
|
|
finally {
|
|
Pop-Location
|
|
}
|
|
|
|
$packer = `
|
|
".\target\release\rustdesk-portable-packer.exe"
|
|
|
|
if (-not (Test-Path $packer)) {
|
|
throw "rustdesk-portable-packer.exe not found"
|
|
}
|
|
|
|
$output = `
|
|
".\dist\rustdesk-1.4.9-custom-windows-x86_64.exe"
|
|
|
|
Copy-Item `
|
|
$packer `
|
|
$output `
|
|
-Force
|
|
|
|
$hash = Get-FileHash `
|
|
$output `
|
|
-Algorithm SHA256
|
|
|
|
$hashLine = `
|
|
"$($hash.Hash.ToLower()) $(Split-Path $output -Leaf)"
|
|
|
|
$hashLine | Set-Content `
|
|
"$output.sha256" `
|
|
-Encoding ASCII
|
|
|
|
Write-Host ""
|
|
Write-Host "============================================"
|
|
Write-Host "Windows portable build completed successfully"
|
|
Write-Host "============================================"
|
|
Write-Host $output
|
|
Write-Host $hashLine
|
|
|
|
- name: Upload Windows build
|
|
uses: https://github.com/actions/upload-artifact@v7
|
|
with:
|
|
name: rustdesk-1.4.9-custom-windows-x86_64
|
|
path: |
|
|
rustdesk/dist/rustdesk-1.4.9-custom-windows-x86_64.exe
|
|
rustdesk/dist/rustdesk-1.4.9-custom-windows-x86_64.exe.sha256
|
|
rustdesk/dist/rustdesk/
|
|
if-no-files-found: error
|
|
retention-days: 14
|