[CmdletBinding()] param( [string]$Url = '', [switch]$ForceRefresh ) $ErrorActionPreference = 'Stop' [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 $MdkVersion = '0.37.0' function Test-SevenZipArchive { param([string]$Path) if (-not (Test-Path $Path)) { return $false } $stream = [System.IO.File]::OpenRead($Path) try { if ($stream.Length -lt 6) { return $false } $buffer = New-Object byte[] 6 [void]$stream.Read($buffer, 0, 6) } finally { $stream.Dispose() } $magic = 0x37, 0x7A, 0xBC, 0xAF, 0x27, 0x1C for ($i = 0; $i -lt 6; $i++) { if ($buffer[$i] -ne $magic[$i]) { return $false } } return $true } function Resolve-CMakeExecutable { $pathCommand = Get-Command 'cmake.exe' -ErrorAction SilentlyContinue if ($pathCommand) { return $pathCommand.Source } $visualStudioInstallations = @() $vswherePath = Join-Path ${Env:ProgramFiles(x86)} 'Microsoft Visual Studio\Installer\vswhere.exe' if (Test-Path $vswherePath) { $visualStudioInstallations += @( & $vswherePath -products '*' -property installationPath 2>$null ) } foreach ($programFilesRoot in @($Env:ProgramFiles, ${Env:ProgramFiles(x86)})) { if (-not $programFilesRoot) { continue } foreach ($edition in @('BuildTools', 'Community', 'Professional', 'Enterprise')) { $visualStudioInstallations += Join-Path $programFilesRoot "Microsoft Visual Studio\2022\$edition" } } foreach ($installationPath in $visualStudioInstallations | Select-Object -Unique) { if (-not $installationPath) { continue } $candidate = Join-Path $installationPath 'Common7\IDE\CommonExtensions\Microsoft\CMake\CMake\bin\cmake.exe' if (Test-Path $candidate) { return $candidate } } $androidSdkRoots = @( $Env:ANDROID_SDK_ROOT, $Env:ANDROID_HOME, $(if ($Env:LOCALAPPDATA) { Join-Path $Env:LOCALAPPDATA 'Android\sdk' }) ) | Where-Object { $_ -and (Test-Path $_) } | Select-Object -Unique foreach ($androidSdkRoot in $androidSdkRoots) { $cmakeRoot = Join-Path $androidSdkRoot 'cmake' if (-not (Test-Path $cmakeRoot)) { continue } $candidate = Get-ChildItem $cmakeRoot -Directory -ErrorAction SilentlyContinue | Sort-Object Name -Descending | ForEach-Object { Join-Path $_.FullName 'bin\cmake.exe' } | Where-Object { Test-Path $_ } | Select-Object -First 1 if ($candidate) { return $candidate } } return $null } $ProjectRoot = Split-Path -Parent $PSScriptRoot Set-Location $ProjectRoot $PackageConfig = Join-Path $ProjectRoot '.dart_tool\package_config.json' if (-not (Test-Path $PackageConfig)) { throw "package_config.json not found: $PackageConfig (run flutter pub get first)" } $config = Get-Content $PackageConfig -Raw | ConvertFrom-Json $fvp = $config.packages | Where-Object { $_.name -eq 'fvp' } | Select-Object -First 1 if (-not $fvp) { throw 'Package fvp not found in .dart_tool/package_config.json' } $fvpRoot = [Uri]$fvp.rootUri if (-not $fvpRoot.IsFile) { throw "Unsupported fvp rootUri: $($fvp.rootUri)" } $fvpWindowsDir = Join-Path $fvpRoot.LocalPath 'windows' if (-not (Test-Path $fvpWindowsDir)) { throw "fvp windows directory not found: $fvpWindowsDir" } $sdkDir = Join-Path $fvpWindowsDir 'mdk-sdk' $sdkVersionMarkerPath = Join-Path $sdkDir '.smplayer-mdk-version' $archivePath = Join-Path $fvpWindowsDir "mdk-sdk-windows-x64-v$MdkVersion-vs2026.7z" if ($ForceRefresh) { Write-Host "==> Force refreshing fvp mdk-sdk v$MdkVersion" -ForegroundColor Yellow if (Test-Path $sdkDir) { Remove-Item $sdkDir -Recurse -Force } if (Test-Path $archivePath) { Remove-Item $archivePath -Force } } if (Test-Path $sdkDir) { $installedMdkVersion = if (Test-Path $sdkVersionMarkerPath) { (Get-Content $sdkVersionMarkerPath -Raw).Trim() } else { '' } if ($installedMdkVersion -eq $MdkVersion) { Write-Host "==> fvp mdk-sdk v$MdkVersion already exists: $sdkDir" -ForegroundColor Green exit 0 } $displayVersion = if ($installedMdkVersion) { $installedMdkVersion } else { 'unknown' } Write-Host "==> Replacing cached mdk-sdk v$displayVersion with v$MdkVersion" -ForegroundColor Yellow Remove-Item $sdkDir -Recurse -Force } $candidates = @() if ($Url) { $candidates += $Url } else { $candidates += "https://github.com/wang-bin/mdk-sdk/releases/download/v$MdkVersion/mdk-sdk-windows-x64-vs2026.7z" } if ((Test-Path $archivePath) -and -not (Test-SevenZipArchive $archivePath)) { Write-Host "==> Cached archive is not a valid 7z, removing: $archivePath" -ForegroundColor Yellow Remove-Item $archivePath -Force } if (-not (Test-Path $archivePath)) { $downloaded = $false :outer foreach ($candidate in $candidates) { $maxAttempts = 3 for ($attempt = 1; $attempt -le $maxAttempts; $attempt++) { Write-Host "==> Downloading mdk-sdk (attempt $attempt/$maxAttempts): $candidate" -ForegroundColor Cyan try { Invoke-WebRequest -Uri $candidate -OutFile $archivePath ` -UseBasicParsing -MaximumRedirection 10 ` -UserAgent 'Mozilla/5.0' -TimeoutSec 120 } catch { Write-Host " download failed: $($_.Exception.Message)" -ForegroundColor Yellow if (Test-Path $archivePath) { Remove-Item $archivePath -Force } if ($attempt -lt $maxAttempts) { $delay = $attempt * 10 Write-Host " retrying in ${delay}s..." -ForegroundColor Yellow Start-Sleep -Seconds $delay } continue } if (Test-SevenZipArchive $archivePath) { $downloaded = $true break outer } $size = (Get-Item $archivePath).Length Write-Host " not a valid 7z archive (size=$size bytes), trying next" -ForegroundColor Yellow Remove-Item $archivePath -Force break # bad content, skip retries for this URL } } if (-not $downloaded) { throw "Failed to download a valid mdk-sdk archive from: $($candidates -join ', ')" } } Write-Host "==> Extracting mdk-sdk to: $fvpWindowsDir" -ForegroundColor Cyan $sevenZipCommand = Get-Command '7z.exe' -ErrorAction SilentlyContinue $sevenZip = if ($sevenZipCommand) { $sevenZipCommand.Source } else { @( "$Env:ProgramFiles\7-Zip\7z.exe", "${Env:ProgramFiles(x86)}\7-Zip\7z.exe" ) | Where-Object { Test-Path $_ } | Select-Object -First 1 } if ($sevenZip) { & $sevenZip x '-y' "-o$fvpWindowsDir" $archivePath } else { $cmakeExecutable = Resolve-CMakeExecutable if (-not $cmakeExecutable) { throw 'Neither 7-Zip nor CMake was found. Install the Visual Studio C++ CMake tools or 7-Zip, then retry.' } Write-Host "==> Using CMake: $cmakeExecutable" -ForegroundColor DarkGray Push-Location $fvpWindowsDir try { & $cmakeExecutable -E tar xvf $archivePath } finally { Pop-Location } } if ($LASTEXITCODE -ne 0) { throw "Failed to extract mdk-sdk (exit $LASTEXITCODE)" } if (-not (Test-Path $sdkDir)) { throw "mdk-sdk not found after extraction: $sdkDir" } Set-Content -Path $sdkVersionMarkerPath -Value $MdkVersion -NoNewline Write-Host "==> fvp mdk-sdk v$MdkVersion ready: $sdkDir" -ForegroundColor Green