95 lines
7.0 KiB
PowerShell
95 lines
7.0 KiB
PowerShell
# Build-machine only: download once, then stage a self-contained Windows x64 app.
|
|
[CmdletBinding()]
|
|
param(
|
|
[string]$Destination,
|
|
[switch]$StageOnly,
|
|
[string]$Arch = 'amd64'
|
|
)
|
|
$ErrorActionPreference = 'Stop'
|
|
# pwsh callers can pass PSModulePath without Windows PowerShell's bundled modules.
|
|
$env:PSModulePath = "$PSHOME\Modules;" + $env:PSModulePath
|
|
if ($Arch -ne 'amd64') { throw 'Windows runtime currently supports amd64 only; do not ship an ARM64 executable with x64 tools.' }
|
|
$root = Split-Path $PSScriptRoot -Parent
|
|
$thirdParty = Join-Path $root 'third_party'
|
|
$cache = Join-Path $root '.task/runtime-downloads'
|
|
New-Item -ItemType Directory -Force $cache | Out-Null
|
|
|
|
function Download([string]$Url, [string]$Name, [string]$Hash = '') {
|
|
$target = Join-Path $cache $Name
|
|
if (!(Test-Path -LiteralPath $target)) {
|
|
Invoke-WebRequest -Uri $Url -OutFile "$target.tmp" -UseBasicParsing
|
|
Move-Item -LiteralPath "$target.tmp" -Destination $target -Force
|
|
}
|
|
if ($Hash -and (Get-FileHash -LiteralPath $target -Algorithm SHA256).Hash -ne $Hash) {
|
|
throw "Checksum mismatch: $target. Remove this cached file and retry."
|
|
}
|
|
return $target
|
|
}
|
|
|
|
function Copy-RuntimeFile([string]$Source, [string]$Target) {
|
|
if ((Test-Path -LiteralPath $Target) -and (Get-FileHash -LiteralPath $Source).Hash -eq (Get-FileHash -LiteralPath $Target).Hash) { return }
|
|
New-Item -ItemType Directory -Force (Split-Path $Target -Parent) | Out-Null
|
|
Copy-Item -LiteralPath $Source -Destination $Target -Force
|
|
}
|
|
|
|
if (!$StageOnly) {
|
|
& npm.cmd --prefix (Join-Path $root 'runtime/filesystem') run stage
|
|
if ($LASTEXITCODE -ne 0) { throw 'Cannot prepare bundled Filesystem MCP; build machine needs Node >= 24 and npm.' }
|
|
$zip = Download 'https://github.com/Genymobile/scrcpy/releases/download/v5.0.1/scrcpy-win64-v5.0.1.zip' 'scrcpy-win64-v5.0.1.zip' 'b12a2c4ee8be317422451fc7dcf8ee20a71b5ea7ef9ad73ddd825a25316227a5'
|
|
$scrcpy = Join-Path $cache 'scrcpy-win64-v5.0.1'
|
|
Expand-Archive -LiteralPath $zip -DestinationPath $cache -Force
|
|
New-Item -ItemType Directory -Force (Join-Path $thirdParty 'platform-tools'), (Join-Path $thirdParty 'scrcpy') | Out-Null
|
|
foreach ($name in @('adb.exe', 'AdbWinApi.dll', 'AdbWinUsbApi.dll')) {
|
|
Copy-RuntimeFile (Join-Path $scrcpy $name) (Join-Path $thirdParty "platform-tools/$name")
|
|
}
|
|
Copy-Item -LiteralPath (Join-Path $scrcpy 'scrcpy-server') -Destination (Join-Path $thirdParty 'scrcpy/scrcpy-server-v5.0.1') -Force
|
|
$license = Download 'https://raw.githubusercontent.com/Genymobile/scrcpy/v5.0.1/LICENSE' 'scrcpy-LICENSE.txt'
|
|
Copy-Item -LiteralPath $license -Destination (Join-Path $thirdParty 'scrcpy/LICENSE.txt') -Force
|
|
|
|
$zip = Download 'https://www.gyan.dev/ffmpeg/builds/packages/ffmpeg-8.1.2-essentials_build.zip' 'ffmpeg-8.1.2-essentials_build.zip' 'db580001caa24ac104c8cb856cd113a87b0a443f7bdf47d8c12b1d740584a2ec'
|
|
Expand-Archive -LiteralPath $zip -DestinationPath $cache -Force
|
|
$ffmpeg = Join-Path $cache 'ffmpeg-8.1.2-essentials_build'
|
|
New-Item -ItemType Directory -Force (Join-Path $thirdParty 'ffmpeg') | Out-Null
|
|
Copy-Item -LiteralPath (Join-Path $ffmpeg 'bin/ffmpeg.exe') -Destination (Join-Path $thirdParty 'ffmpeg') -Force
|
|
Copy-Item -LiteralPath (Join-Path $ffmpeg 'LICENSE') -Destination (Join-Path $thirdParty 'ffmpeg') -Force
|
|
Copy-Item -LiteralPath (Join-Path $ffmpeg 'README.txt') -Destination (Join-Path $thirdParty 'ffmpeg') -Force
|
|
|
|
# Fixed Version runs privately beside our executable; no runtime installer or network on clients.
|
|
if (!(Test-Path (Join-Path $thirdParty 'webview2/msedgewebview2.exe'))) {
|
|
$cab = Download 'https://msedge.sf.dl.delivery.mp.microsoft.com/filestreamingservice/files/b7919cc9-680d-4253-bf32-732988e68aa6/Microsoft.WebView2.FixedVersionRuntime.156.0.4314.58.x64.cab' 'webview2-156.0.4314.58-x64.cab' '857dcfd6f7035508a29645fa2978c3a6a841f220df77cc366d318894e19f4792'
|
|
$expanded = Join-Path $cache 'webview2-expanded'
|
|
New-Item -ItemType Directory -Force $expanded | Out-Null
|
|
& expand.exe $cab '-F:*' $expanded | Out-Null
|
|
if ($LASTEXITCODE -ne 0) { throw 'Cannot expand WebView2 Fixed Version CAB' }
|
|
$browser = @(Get-ChildItem -LiteralPath $expanded -Filter msedgewebview2.exe -Recurse)
|
|
if ($browser.Count -ne 1) { throw 'Invalid WebView2 CAB contents' }
|
|
New-Item -ItemType Directory -Force (Join-Path $thirdParty 'webview2') | Out-Null
|
|
Copy-Item -Path (Join-Path $browser[0].DirectoryName '*') -Destination (Join-Path $thirdParty 'webview2') -Recurse -Force
|
|
}
|
|
$manifest = @{ platform = 'windows/amd64'; scrcpy = '5.0.1'; ffmpeg = '8.1.2'; webview2 = '156.0.4314.58' }
|
|
$manifest | ConvertTo-Json | Set-Content (Join-Path $thirdParty 'runtime-manifest.json') -Encoding UTF8
|
|
}
|
|
|
|
$required = @('platform-tools/adb.exe', 'platform-tools/AdbWinApi.dll', 'platform-tools/AdbWinUsbApi.dll', 'scrcpy/scrcpy-server-v5.0.1', 'scrcpy/LICENSE.txt', 'ffmpeg/ffmpeg.exe', 'ffmpeg/LICENSE', 'webview2/msedgewebview2.exe', 'runtime-manifest.json', 'mcp-filesystem/node.exe', 'mcp-filesystem/NODE-LICENSE.txt', 'mcp-filesystem/runtime.json', 'mcp-filesystem/node_modules/@modelcontextprotocol/server-filesystem/dist/index.js')
|
|
foreach ($file in $required) {
|
|
if (!(Test-Path -LiteralPath (Join-Path $thirdParty $file))) { throw "Missing bundled runtime: $file. Run scripts/sync-windows-runtime.ps1 on the build machine." }
|
|
}
|
|
$manifest = Get-Content (Join-Path $thirdParty 'runtime-manifest.json') -Raw | ConvertFrom-Json
|
|
if ($manifest.platform -ne 'windows/amd64') { throw 'Wrong platform runtime; resync Windows dependencies.' }
|
|
$nodeIdentity = & (Join-Path $thirdParty 'mcp-filesystem/node.exe') -p 'JSON.stringify({platform:process.platform,arch:process.arch,major:parseInt(process.versions.node)})' | ConvertFrom-Json
|
|
if ($LASTEXITCODE -ne 0 -or $nodeIdentity.platform -ne 'win32' -or $nodeIdentity.arch -ne 'x64' -or $nodeIdentity.major -lt 24) { throw 'Wrong private Node runtime; restage Filesystem MCP on Windows x64.' }
|
|
if ((Get-FileHash (Join-Path $thirdParty 'scrcpy/scrcpy-server-v5.0.1')).Hash -ne '764eb6f79811d5211fe9df341120882ba9994c7a61b897d7bf3fb662e53bc536') { throw 'scrcpy server version/checksum mismatch' }
|
|
if ($Destination) {
|
|
New-Item -ItemType Directory -Force $Destination | Out-Null
|
|
foreach ($folder in @('platform-tools', 'scrcpy', 'ffmpeg', 'webview2', 'mcp-filesystem')) {
|
|
$sourceDir = Join-Path $thirdParty $folder
|
|
foreach ($file in Get-ChildItem -LiteralPath $sourceDir -File -Recurse) {
|
|
$relative = $file.FullName.Substring($sourceDir.Length).TrimStart('\')
|
|
Copy-RuntimeFile $file.FullName (Join-Path (Join-Path $Destination $folder) $relative)
|
|
}
|
|
}
|
|
Copy-Item -LiteralPath (Join-Path $thirdParty 'runtime-manifest.json') -Destination $Destination -Force
|
|
Copy-Item -LiteralPath (Join-Path $thirdParty 'RUNTIME-NOTICES.txt') -Destination $Destination -Force
|
|
}
|
|
Write-Host 'Windows runtime verified (ADB + scrcpy server + FFmpeg + private WebView2 + Filesystem MCP).'
|