diff --git a/res/bootstrap-windows.ps1 b/res/bootstrap-windows.ps1 new file mode 100755 index 0000000..a258ea5 --- /dev/null +++ b/res/bootstrap-windows.ps1 @@ -0,0 +1,204 @@ +# bootstrap-windows.ps1 +# +# One-shot setup for building RustDesk 1.4.7 (our fork) on Windows 11. +# Run as Administrator from a PowerShell window. +# +# What it does: +# 1. Verify / install Visual Studio 2022 Build Tools (Desktop C++ workload) +# 2. Install Rust (stable-msvc) via rustup +# 3. Install Flutter 3.44+ (Chinese mirror) +# 4. Install VCPKG and the C++ deps (libvpx, libyuv, opus, aom) for x64-windows-static +# 5. Clone the fork from git.cardsoon.com +# 6. Apply the post-clone patches (google_fonts const -> final) +# +# This script is idempotent: re-running it skips already-completed steps. +# Run-time: ~30-60 minutes (mostly VCPKG building C++ deps). +# +# Usage (from an "x64 Native Tools Command Prompt for VS 2022"): +# powershell -ExecutionPolicy Bypass -File .\res\bootstrap-windows.ps1 +# +# After this finishes, run: +# .\res\build-windows.ps1 + +$ErrorActionPreference = "Stop" +Set-StrictMode -Version Latest + +# Pretty logging +function Write-Section { param($msg) Write-Host "`n=== $msg ===" -ForegroundColor Cyan } +function Write-Ok { param($msg) Write-Host " [OK] $msg" -ForegroundColor Green } +function Write-Warn { param($msg) Write-Host " [WARN] $msg" -ForegroundColor Yellow } +function Write-Err { param($msg) Write-Host " [ERR] $msg" -ForegroundColor Red } + +# ------- Config ------- +$PROJECT_ROOT = "C:\prj\rustdesk" +$VCPKG_ROOT = "C:\vcpkg" +$FLUTTER_ROOT = "C:\flutter" +$FLUTTER_VERSION = "3.44.1-stable" +$RUST_TOOLCHAIN = "stable-msvc" +$GIT_URL = "https://git.cardsoon.com/xuwenwei/RustDesk.git" + +# Chinese mirrors (faster in CN; remove if you're elsewhere) +$PUB_HOSTED_URL = "https://pub.flutter-io.cn" +$FLUTTER_STORAGE_BASE_URL = "https://storage.flutter-io.cn" + +# ------- 1. Verify Visual Studio 2022 Build Tools ------- +Write-Section "1/7 Visual Studio 2022 Build Tools" + +$vsWhere = "${env:ProgramFiles(x86)}\Microsoft Visual Studio\Installer\vswhere.exe" +if (Test-Path $vsWhere) { + $vs = & $vsWhere -latest -property installationPath 2>$null + if ($vs) { + Write-Ok "Found VS install: $vs" + } else { + Write-Err "vswhere.exe exists but returned no installation." + Write-Host "Please install Visual Studio 2022 Build Tools with 'Desktop development with C++' workload:" + Write-Host " https://visualstudio.microsoft.com/visual-studio-build-tools/" + exit 1 + } +} else { + Write-Err "Visual Studio 2022 Build Tools not detected." + Write-Host "Please install it with 'Desktop development with C++' workload:" + Write-Host " https://visualstudio.microsoft.com/visual-studio-build-tools/" + Write-Host " Required components: MSVC v143, Windows 11 SDK, C++ CMake tools" + exit 1 +} + +# Detect the vcvars batch file (needed for cl.exe / link.exe on PATH) +$vcvars = Get-ChildItem -Path $vs -Recurse -Filter "vcvars64.bat" -ErrorAction SilentlyContinue | Select-Object -First 1 +if (-not $vcvars) { + Write-Err "vcvars64.bat not found under $vs" + exit 1 +} +$vcvarsPath = $vcvars.FullName +Write-Ok "Found vcvars64: $vcvarsPath" + +# ------- 2. Install Rust ------- +Write-Section "2/7 Rust (stable-msvc)" + +$rustupExe = "$env:USERPROFILE\.cargo\bin\rustup.exe" +$cargoExe = "$env:USERPROFILE\.cargo\bin\cargo.exe" +if (Test-Path $cargoExe) { + Write-Ok "cargo already installed: $cargoExe" +} else { + Write-Host " Installing rustup..." + Invoke-WebRequest -Uri "https://win.rustup.rs/x86_64" -OutFile "$env:TEMP\rustup-init.exe" + & "$env:TEMP\rustup-init.exe" -y --default-toolchain $RUST_TOOLCHAIN + Remove-Item "$env:TEMP\rustup-init.exe" + Write-Ok "rustup installed" +} +$env:Path = "$env:USERPROFILE\.cargo\bin;$env:Path" +& rustc --version +Write-Ok "rustc OK" + +# ------- 3. Install Flutter ------- +Write-Section "3/7 Flutter $FLUTTER_VERSION (Chinese mirror)" + +if (Test-Path "$FLUTTER_ROOT\bin\flutter.bat") { + Write-Ok "Flutter already installed at $FLUTTER_ROOT" +} else { + Write-Host " Downloading Flutter SDK..." + $zipUrl = "$FLUTTER_STORAGE_BASE_URL/flutter_infra_release/releases/stable/windows/flutter_windows_$FLUTTER_VERSION.zip" + $zipPath = "$env:TEMP\flutter.zip" + Invoke-WebRequest -Uri $zipUrl -OutFile $zipPath + Write-Host " Extracting to $FLUTTER_ROOT..." + Expand-Archive -Path $zipPath -DestinationPath "C:\" + Remove-Item $zipPath + Write-Ok "Flutter installed at $FLUTTER_ROOT" +} + +# Persist Chinese mirror env vars for the user +[Environment]::SetEnvironmentVariable("PUB_HOSTED_URL", $PUB_HOSTED_URL, "User") +[Environment]::SetEnvironmentVariable("FLUTTER_STORAGE_BASE_URL", $FLUTTER_STORAGE_BASE_URL, "User") +$env:PUB_HOSTED_URL = $PUB_HOSTED_URL +$env:FLUTTER_STORAGE_BASE_URL = $FLUTTER_STORAGE_BASE_URL +$env:Path = "$FLUTTER_ROOT\bin;$env:Path" + +# Use the absolute path to flutter.bat so the rest of the script can find it +$flutterBat = "$FLUTTER_ROOT\bin\flutter.bat" +& $flutterBat --version +& $flutterBat config --no-analytics | Out-Null +& $flutterBat doctor | Out-Null +Write-Ok "Flutter doctor OK" + +# ------- 4. Install VCPKG and C++ deps ------- +Write-Section "4/7 VCPKG + C++ dependencies (libvpx, libyuv, opus, aom)" + +if (-not (Test-Path $VCPKG_ROOT)) { + Write-Host " Cloning VCPKG to $VCPKG_ROOT..." + git clone https://github.com/microsoft/vcpkg $VCPKG_ROOT + & "$VCPKG_ROOT\bootstrap-vcpkg.bat" -disableMetrics + Write-Ok "VCPKG installed" +} else { + Write-Ok "VCPKG already at $VCPKG_ROOT" +} +[Environment]::SetEnvironmentVariable("VCPKG_ROOT", $VCPKG_ROOT, "User") +$env:VCPKG_ROOT = $VCPKG_ROOT +$env:Path = "$VCPKG_ROOT;$env:Path" + +Write-Host " Installing C++ deps (x64-windows-static, ~5-10 minutes)..." +& "$VCPKG_ROOT\vcpkg.exe" install --triplet=x64-windows-static libvpx libyuv opus aom +Write-Ok "C++ deps installed" + +# ------- 5. Install flutter_rust_bridge_codegen ------- +Write-Section "5/7 flutter_rust_bridge_codegen (1.80.1)" + +# cargo install outputs the bin to %USERPROFILE%\.cargo\bin +$frbcBin = "$env:USERPROFILE\.cargo\bin\flutter_rust_bridge_codegen.exe" +if (Test-Path $frbcBin) { + Write-Ok "flutter_rust_bridge_codegen already installed" +} else { + Write-Host " Installing (5-10 minutes)..." + & cargo install flutter_rust_bridge_codegen --version 1.80.1 --features uuid --locked + Write-Ok "Installed" +} + +# ------- 6. Clone the fork ------- +Write-Section "6/7 Clone the fork from git.cardsoon.com" + +if (Test-Path $PROJECT_ROOT) { + Write-Ok "Project already cloned at $PROJECT_ROOT" + Push-Location $PROJECT_ROOT + & git fetch origin | Out-Null + & git status + Pop-Location +} else { + New-Item -ItemType Directory -Path (Split-Path $PROJECT_ROOT) -Force | Out-Null + git clone $GIT_URL $PROJECT_ROOT + Push-Location $PROJECT_ROOT + & git checkout main + Pop-Location + Write-Ok "Fork cloned to $PROJECT_ROOT" +} + +# ------- 7. Patch google_fonts (one-liner, per-machine) ------- +Write-Section "7/7 Patch google_fonts pub cache (per-machine)" + +$googleFontsFile = Join-Path $env:USERPROFILE ".pub-cache\hosted\pub.dev\google_fonts-5.0.0\lib\src\google_fonts_variant.dart" +if (Test-Path $googleFontsFile) { + $content = Get-Content $googleFontsFile -Raw + if ($content -match '^final _fontWeightToFilenameWeightParts') { + Write-Ok "google_fonts already patched" + } else { + $patched = $content -replace '^const _fontWeightToFilenameWeightParts', 'final _fontWeightToFilenameWeightParts' + Set-Content -Path $googleFontsFile -Value $patched -NoNewline + Write-Ok "Patched google_fonts_variant.dart (const -> final)" + } +} else { + Write-Warn "google_fonts_variant.dart not found at $googleFontsFile" + Write-Host " It will be created on first 'flutter pub get'. Re-run this script after that, OR patch it manually:" + Write-Host " change 'const _fontWeightToFilenameWeightParts' to 'final _fontWeightToFilenameWeightParts'" +} + +# ------- Done ------- +Write-Section "Bootstrap complete" +Write-Host "Next step: open a new shell with vcvars64 sourced, then run:" +Write-Host " cd $PROJECT_ROOT" +Write-Host " .\res\build-windows.ps1" +Write-Host "" +Write-Host "If the build is interrupted, just re-run build-windows.ps1 - it's incremental." +Write-Host "" +Write-Host "Output: $PROJECT_ROOT\flutter\build\windows\x64\runner\Release\" +Write-Host " (zip the Release\ folder for distribution)" + +Write-Host "" +Write-Host "Note: This script must be re-run any time you 'flutter pub cache clean'." diff --git a/res/build-windows.ps1 b/res/build-windows.ps1 new file mode 100755 index 0000000..d68a707 --- /dev/null +++ b/res/build-windows.ps1 @@ -0,0 +1,131 @@ +# build-windows.ps1 +# +# Build RustDesk 1.4.7 (our fork) on Windows 11. +# Run from an "x64 Native Tools Command Prompt for VS 2022" PowerShell window. +# +# What it does: +# 1. flutter pub get +# 2. flutter_rust_bridge_codegen (regenerates generated_bridge.dart) +# — REMEMBER: hand-patch the 3 sites in generated_bridge.dart! +# 3. cargo build --release +# 4. flutter build windows --release +# 5. Optional: signtool sign the .exe +# 6. Zip up the Release/ folder +# +# Re-run this script any time: incremental builds are fast (~30 sec for +# Flutter, ~1 min for Rust when nothing changed). + +$ErrorActionPreference = "Stop" +Set-StrictMode -Version Latest + +function Write-Section { param($msg) Write-Host "`n=== $msg ===" -ForegroundColor Cyan } +function Write-Ok { param($msg) Write-Host " [OK] $msg" -ForegroundColor Green } +function Write-Warn { param($msg) Write-Host " [WARN] $msg" -ForegroundColor Yellow } +function Write-Err { param($msg) Write-Host " [ERR] $msg" -ForegroundColor Red } + +# ------- Config ------- +$PROJECT_ROOT = "C:\prj\rustdesk" +$VERSION = if ($env:VERSION) { $env:VERSION } else { "1.4.7" } +$ARCH = "x86_64" + +# Should we sign? Set $env:SKIP_SIGN=1 to skip. +$SKIP_SIGN = if ($env:SKIP_SIGN) { $env:SKIP_SIGN -eq "1" } else { $true } +# Certificate path. Set $env:CERT_PATH to a .pfx file to sign. +$CERT_PATH = $env:CERT_PATH +$CERT_PASSWORD = $env:CERT_PASSWORD + +Push-Location $PROJECT_ROOT + +# ------- 1. flutter pub get ------- +Write-Section "1/6 flutter pub get" +& "$env:FLUTTER_ROOT\bin\flutter.bat" pub get +Write-Ok "deps ready" + +# ------- 2. flutter_rust_bridge_codegen ------- +Write-Section "2/6 flutter_rust_bridge_codegen (Flutter <-> Rust FFI bindings)" +& "$env:USERPROFILE\.cargo\bin\flutter_rust_bridge_codegen.exe" ` + --rust-input ./src/flutter_ffi.rs ` + --dart-output ./flutter/lib/generated_bridge.dart ` + --c-output ./flutter/windows/runner/bridge_generated.h +Write-Ok "FFI bindings regenerated" +Write-Host "" +Write-Host " >>> REMINDER: re-apply the 3 hand-patches to flutter/lib/generated_bridge.dart <<<" -ForegroundColor Yellow +Write-Host " 1. api2wire_int_32_list: asTypedList(raw.length).setAll(0, raw)" +Write-Host " -> .cast().asTypedList(raw.length).setAll(0, raw)" +Write-Host " 2. api2wire_uint_8_list: asTypedList(raw.length).setAll(0, raw)" +Write-Host " -> .cast().asTypedList(raw.length).setAll(0, raw)" +Write-Host " 3. typedef DartPort = ffi.Int; -> typedef DartPort = ffi.Int64;" +Write-Host "" +Write-Host " (These get regenerated every codegen run. The upstream Rust code" +Write-Host " still has the old API; we patch after each generation.)" +Write-Host "" + +# ------- 3. Rust build ------- +Write-Section "3/6 cargo build --release --features flutter" +& cargo build --release --features flutter +Write-Ok "Rust build OK" + +# ------- 4. Flutter Windows build ------- +Write-Section "4/6 flutter build windows --release" +Push-Location flutter +& "$env:FLUTTER_ROOT\bin\flutter.bat" build windows --release +Pop-Location +Write-Ok "Flutter build OK" + +# ------- 5. (Optional) sign with signtool ------- +Write-Section "5/6 sign RustDesk.exe (optional)" + +$exePath = "flutter\build\windows\x64\runner\Release\RustDesk.exe" +if ($SKIP_SIGN -or -not $CERT_PATH) { + if (-not $CERT_PATH) { + Write-Warn "No CERT_PATH set; skipping signing (unsigned binary)." + } else { + Write-Warn "SKIP_SIGN=1; skipping signing." + } +} elseif (-not (Test-Path $CERT_PATH)) { + Write-Err "CERT_PATH=$CERT_PATH does not exist. Aborting." + exit 1 +} else { + Write-Host " Signing $exePath with $CERT_PATH..." + & signtool sign /f "$CERT_PATH" /p "$CERT_PASSWORD" /t http://timestamp.digicert.com "$exePath" + if ($LASTEXITCODE -ne 0) { + Write-Err "signtool failed with exit $LASTEXITCODE" + exit 1 + } + Write-Ok "Signed" + & signtool verify /pa "$exePath" | Out-Null + if ($LASTEXITCODE -ne 0) { + Write-Warn "Signature verification failed; binary still works (SmartScreen will warn on first launch)" + } else { + Write-Ok "Signature verified" + } +} + +# ------- 6. Zip up ------- +Write-Section "6/6 Zip the Release folder" + +$releaseDir = "flutter\build\windows\x64\runner\Release" +$zipPath = "rustdesk-$VERSION-$ARCH.zip" +if (Test-Path $zipPath) { Remove-Item $zipPath -Force } +Compress-Archive -Path "$releaseDir\*" -DestinationPath $zipPath -CompressionLevel Optimal +$size = "{0:N1} MB" -f ((Get-Item $zipPath).Length / 1MB) +Write-Ok "Created: $zipPath ($size)" + +Pop-Location + +Write-Section "Build complete" +Write-Host "Output:" +Write-Host " Build: $PROJECT_ROOT\flutter\build\windows\x64\runner\Release\" +Write-Host " Zip: $PROJECT_ROOT\rustdesk-$VERSION-$ARCH.zip" +Write-Host "" +Write-Host "Distribution:" +Write-Host " 1. Share rustdesk-$VERSION-$ARCH.zip with your users" +Write-Host " 2. Each user unzips and double-clicks RustDesk.exe" +Write-Host " 3. First launch: Windows SmartScreen will warn ('more info' -> 'run anyway')" +Write-Host " 4. Or: sign the .exe with a real code-signing cert (no SmartScreen warning)" +Write-Host "" +Write-Host "Configure on the Win host:" +Write-Host " ID Server: 114.55.133.123:21116" +Write-Host " Relay: 114.55.133.123:21117" +Write-Host " API: http://114.55.133.123:21118" +Write-Host " Key: EXdBNGKAMYAKCzLGp0+5NnFIv9MCs1WfBYy1tFBKS78="