Add Windows bootstrap + build scripts (res/bootstrap-windows.ps1, res/build-windows.ps1)
bootstrap-windows.ps1: one-shot setup for a fresh Win 11 host. Checks for VS 2022 Build Tools, installs Rust via rustup, Flutter 3.44+ with the Chinese mirror, VCPKG with the x64-windows-static deps (libvpx, libyuv, opus, aom), flutter_rust_bridge_codegen, clones the fork from git.cardsoon.com, and patches google_fonts const->final in the pub cache. Idempotent (re-runs skip already-done steps). ~30-60 min on first run. build-windows.ps1: day-to-day build script. Runs flutter pub get, flutter_rust_bridge_codegen (with a reminder to re-apply the 3 hand patches to generated_bridge.dart), cargo build, flutter build windows --release, optionally signtool-signs the .exe (if CERT_PATH env var is set), and zips the Release/ folder into rustdesk-VERSION-ARCH.zip. Incremental rebuilds are fast. These two scripts mirror res/post-build-mac.sh in spirit: same purpose, different platform. Both produce a redistributable artifact. Run sequence on a fresh Win host: 1. Open 'x64 Native Tools Command Prompt for VS 2022' 2. powershell -ExecutionPolicy Bypass -File .\res\bootstrap-windows.ps1 3. .\res\build-windows.ps1 Output: rustdesk-1.4.7-x86_64.zip
This commit is contained in:
Executable
+204
@@ -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'."
|
||||||
Executable
+131
@@ -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<ffi.Int32>().asTypedList(raw.length).setAll(0, raw)"
|
||||||
|
Write-Host " 2. api2wire_uint_8_list: asTypedList(raw.length).setAll(0, raw)"
|
||||||
|
Write-Host " -> .cast<ffi.Uint8>().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="
|
||||||
Reference in New Issue
Block a user