diff --git a/scripts/build-windows.ps1 b/scripts/build-windows.ps1 index dfd2fcd..8e97e7f 100644 --- a/scripts/build-windows.ps1 +++ b/scripts/build-windows.ps1 @@ -1,95 +1,108 @@ <# Локальная сборка преднастроенного RustDesk-клиента под Windows (GUSIK-PC). - Делает: клон rustdesk@пин -> preconfigure (вшить сервер+ключ) -> python build.py --flutter -> dist/. - Тулчейн (Rust 1.75 / LLVM 15 / Flutter 3.24.5 / vcpkg@пин) должен быть уже поднят — - скрипт делает preflight-проверку и подсказывает, чего не хватает. + Клон rustdesk@пин -> preconfigure (вшить сервер+ключ) -> vcpkg install -> python build.py --flutter -> dist/. + + Тулчейн (ставится один раз, см. docs/CODEMAP.md): + Rust 1.75 (rustup), VS Build Tools 2022 (MSVC+CMake+libclang), Flutter 3.24.5, vcpkg@пин. + Пути тулчейна можно переопределить через env FLUTTER_HOME / VCPKG_ROOT. Запуск: pwsh -File scripts\build-windows.ps1 - Опции: -Clean (снести клон и склонировать заново) + Опции: -Clean снести клон и склонировать заново + -SkipBuild только клон+preconfigure (без компиляции) #> [CmdletBinding()] -param( - [switch]$Clean, - [switch]$SkipBuild # только клон+preconfigure, без компиляции (для отладки) -) +param([switch]$Clean, [switch]$SkipBuild) $ErrorActionPreference = 'Stop' -$root = Split-Path -Parent $PSScriptRoot # корень overlay-репо -$src = Join-Path $root 'rustdesk' # клон апстрима +$root = Split-Path -Parent $PSScriptRoot +$src = Join-Path $root 'rustdesk' $dist = Join-Path $root 'dist' -# --- читаем пины --- +# --- пины --- $pins = @{} Get-Content (Join-Path $root 'upstream.txt') | Where-Object { $_ -match '^\s*[A-Z]' } | ForEach-Object { $k,$v = $_ -split '=',2; $pins[$k.Trim()] = $v.Trim() } -$TAG = $pins['RUSTDESK_TAG'] -$REPO = $pins['RUSTDESK_REPO'] -Write-Host "== RustDesk custom build == tag=$TAG" -ForegroundColor Cyan +$TAG=$pins['RUSTDESK_TAG']; $REPO=$pins['RUSTDESK_REPO']; $TRIPLET=$pins['VCPKG_TRIPLET'] +Write-Host "== RustDesk custom build == tag=$TAG triplet=$TRIPLET" -ForegroundColor Cyan -# --- загрузка config/server.env --- +# --- пути тулчейна --- +$FlutterHome = if ($env:FLUTTER_HOME) { $env:FLUTTER_HOME } else { 'S:\dev\flutter' } +$VcpkgRoot = if ($env:VCPKG_ROOT) { $env:VCPKG_ROOT } else { 'S:\dev\vcpkg' } +$BashExe = 'C:\Program Files\Git\bin\bash.exe' + +# --- config/server.env --- $envFile = Join-Path $root 'config\server.env' -if (-not (Test-Path $envFile)) { - throw "Нет $envFile. Скопируй config\server.env.example -> config\server.env и заполни RUSTDESK_SERVER/RUSTDESK_PUB_KEY." -} +if (-not (Test-Path $envFile)) { throw "Нет $envFile — скопируй config\server.env.example и заполни RUSTDESK_SERVER/RUSTDESK_PUB_KEY." } Get-Content $envFile | Where-Object { $_ -match '^\s*[A-Z].*=' } | ForEach-Object { - $k,$v = $_ -split '=',2 - Set-Item -Path "Env:$($k.Trim())" -Value $v.Trim() -} -if (-not $env:RUSTDESK_SERVER -or -not $env:RUSTDESK_PUB_KEY) { - throw "В config\server.env не заданы RUSTDESK_SERVER и/или RUSTDESK_PUB_KEY." + $k,$v = $_ -split '=',2; Set-Item -Path "Env:$($k.Trim())" -Value $v.Trim() } +if (-not $env:RUSTDESK_SERVER -or -not $env:RUSTDESK_PUB_KEY) { throw "В config\server.env не заданы RUSTDESK_SERVER/RUSTDESK_PUB_KEY." } -# --- preflight тулчейна --- -function Need($name, $test, $hint) { - if (-not (& $test)) { Write-Host " [нет] $name — $hint" -ForegroundColor Yellow; return $false } - Write-Host " [ok] $name" -ForegroundColor Green; return $true -} -Write-Host "Preflight тулчейна:" -ForegroundColor Cyan -$ok = $true -$ok = (Need 'git' { Get-Command git -EA SilentlyContinue } 'установи Git for Windows') -and $ok -$ok = (Need 'bash' { Get-Command bash -EA SilentlyContinue } 'нужен git-bash для preconfigure.sh') -and $ok -$ok = (Need 'python' { Get-Command python -EA SilentlyContinue } 'нужен Python 3 для build.py') -and $ok -$ok = (Need 'rustup' { Get-Command rustup -EA SilentlyContinue } 'установи rustup') -and $ok -$ok = (Need 'flutter' { Get-Command flutter -EA SilentlyContinue } "Flutter $($pins['FLUTTER_VERSION']) stable в PATH") -and $ok -$ok = (Need 'vcpkg' { $env:VCPKG_ROOT -and (Test-Path (Join-Path $env:VCPKG_ROOT 'vcpkg.exe')) } "склонируй vcpkg@$($pins['VCPKG_COMMIT_ID']), задай VCPKG_ROOT") -and $ok -$ok = (Need 'LLVM' { $env:LIBCLANG_PATH -and (Test-Path $env:LIBCLANG_PATH) } "LLVM $($pins['LLVM_VERSION']), задай LIBCLANG_PATH") -and $ok -if (-not $ok) { throw "Тулчейн неполный — см. docs\CODEMAP.md (раздел 'Windows toolchain')." } +# --- импорт VS dev-env (MSVC/CMake/Windows SDK в PATH) --- +$vsw = "${env:ProgramFiles(x86)}\Microsoft Visual Studio\Installer\vswhere.exe" +$vsPath = & $vsw -latest -products * -property installationPath +if (-not $vsPath) { throw "VS Build Tools не найдены (vswhere)." } +$vcvars = Join-Path $vsPath 'VC\Auxiliary\Build\vcvars64.bat' +Write-Host "Импорт VS dev-env: $vcvars" -ForegroundColor DarkCyan +cmd /c "`"$vcvars`" >nul && set" | ForEach-Object { if ($_ -match '^([^=]+)=(.*)$') { Set-Item "Env:$($matches[1])" $matches[2] } } -# --- клон / обновление до пина --- +# --- env тулчейна на сессию --- +$env:VCPKG_ROOT = $VcpkgRoot +$env:VCPKGRS_TRIPLET = $TRIPLET # для vcpkg-rs крейтов (статик-триплет) +$env:LIBCLANG_PATH = Join-Path $vsPath 'VC\Tools\Llvm\x64\bin' # bindgen (libclang из VS) +$env:PATH = "$FlutterHome\bin;$VcpkgRoot;$env:PATH" + +# --- preflight --- +function Check($n,$ok,$hint){ if($ok){Write-Host " [ok] $n" -ForegroundColor Green}else{Write-Host " [нет] $n — $hint" -ForegroundColor Yellow}; return $ok } +Write-Host "Preflight:" -ForegroundColor Cyan +$all = $true +$all = (Check 'git' ([bool](Get-Command git -EA SilentlyContinue)) 'Git for Windows') -and $all +$all = (Check 'git-bash' (Test-Path $BashExe) "нет $BashExe") -and $all +$all = (Check 'python' ([bool](Get-Command python -EA SilentlyContinue)) 'Python 3') -and $all +$all = (Check "rust $($pins['RUST_VERSION'])" ([bool]((rustup toolchain list) -match $pins['RUST_VERSION'])) "rustup toolchain install $($pins['RUST_VERSION'])") -and $all +$all = (Check 'flutter' (Test-Path "$FlutterHome\bin\flutter.bat") "Flutter в $FlutterHome") -and $all +$all = (Check 'vcpkg' (Test-Path "$VcpkgRoot\vcpkg.exe") "vcpkg в $VcpkgRoot") -and $all +$all = (Check 'cl.exe' ([bool](Get-Command cl.exe -EA SilentlyContinue)) 'MSVC из vcvars') -and $all +$all = (Check 'libclang' (Test-Path (Join-Path $env:LIBCLANG_PATH 'libclang.dll')) "нет libclang.dll в $($env:LIBCLANG_PATH)") -and $all +if (-not $all) { throw "Тулчейн неполный — см. docs\CODEMAP.md." } + +# --- клон/сброс до пина --- if ($Clean -and (Test-Path $src)) { Remove-Item -Recurse -Force $src } if (-not (Test-Path $src)) { - Write-Host "Клонирую rustdesk@$TAG ..." -ForegroundColor Cyan + Write-Host "Клонирую rustdesk@$TAG (+submodule)..." -ForegroundColor Cyan git clone --branch $TAG --depth 1 --recurse-submodules --shallow-submodules $REPO $src } else { - Write-Host "Клон уже есть — сбрасываю патчи до чистого $TAG ..." -ForegroundColor Cyan + Write-Host "Сбрасываю патчи до чистого $TAG..." -ForegroundColor Cyan git -C $src checkout -- . git -C $src submodule foreach --recursive 'git checkout -- .' } - -# зафиксировать Rust 1.75 для этого дерева -Push-Location $src -rustup override set $pins['RUST_VERSION'] | Out-Null -Pop-Location +Push-Location $src; rustup override set $pins['RUST_VERSION'] | Out-Null; Pop-Location # --- preconfigure: вшить сервер+ключ --- -Write-Host "Preconfigure (вшиваю сервер+ключ)..." -ForegroundColor Cyan -bash "$root/scripts/preconfigure.sh" "$src" +Write-Host "Preconfigure (сервер+ключ)..." -ForegroundColor Cyan +& $BashExe "$root/scripts/preconfigure.sh" "$src" +if ($LASTEXITCODE) { throw "preconfigure.sh упал ($LASTEXITCODE)" } +if ($SkipBuild) { Write-Host "SkipBuild — стоп после preconfigure." -ForegroundColor Yellow; return } -if ($SkipBuild) { Write-Host "SkipBuild — остановился после preconfigure." -ForegroundColor Yellow; return } - -# --- сборка --- -Write-Host "Сборка: python build.py --flutter (первый раз долго: vcpkg ffmpeg/aom)..." -ForegroundColor Cyan +# --- vcpkg install (манифест из vcpkg.json; первый раз долго: ffmpeg/aom) --- +Write-Host "vcpkg install ($TRIPLET) — первый раз ОЧЕНЬ долго (ffmpeg/aom из исходников)..." -ForegroundColor Cyan Push-Location $src -python build.py --flutter +& "$VcpkgRoot\vcpkg.exe" install --triplet $TRIPLET --x-install-root="$VcpkgRoot\installed" +if ($LASTEXITCODE) { Pop-Location; throw "vcpkg install упал ($LASTEXITCODE)" } Pop-Location -# --- собрать артефакт --- +# --- сборка --- +Write-Host "python build.py --flutter..." -ForegroundColor Cyan +Push-Location $src +python build.py --flutter +$rc = $LASTEXITCODE +Pop-Location +if ($rc) { throw "build.py упал ($rc)" } + +# --- артефакт --- New-Item -ItemType Directory -Force $dist | Out-Null -$exe = Get-ChildItem -Path $src -Recurse -Filter 'rustdesk*.exe' -EA SilentlyContinue | - Where-Object { $_.FullName -match 'Release|portable' } | Select-Object -First 1 -if ($exe) { - Copy-Item $exe.FullName (Join-Path $dist $exe.Name) -Force - Write-Host "Готово: $(Join-Path $dist $exe.Name)" -ForegroundColor Green -} else { - Write-Host "Сборка завершилась, но .exe не найден автоматически — глянь $src\build и $src\flutter\build." -ForegroundColor Yellow -} +$out = Get-ChildItem -Path $src -Filter 'rustdesk-*-install.exe' -EA SilentlyContinue | Select-Object -First 1 +if (-not $out) { $out = Get-ChildItem -Path $src -Recurse -Filter 'rustdesk*.exe' -EA SilentlyContinue | + Where-Object { $_.FullName -match 'Release' } | Select-Object -First 1 } +if ($out) { Copy-Item $out.FullName (Join-Path $dist $out.Name) -Force; Write-Host "ГОТОВО: $(Join-Path $dist $out.Name)" -ForegroundColor Green } +else { Write-Host "Сборка ок, но .exe не найден — глянь $src (rustdesk-*-install.exe) и $src\flutter\build." -ForegroundColor Yellow }