$ErrorActionPreference = 'Stop' $ProgressPreference = 'SilentlyContinue' $env:PUB_HOSTED_URL = 'https://pub.flutter-io.cn' $env:FLUTTER_STORAGE_BASE_URL = 'https://storage.flutter-io.cn' function Get-FreeGb([string]$letter) { $d = Get-PSDrive -Name $letter -ErrorAction SilentlyContinue if (-not $d) { return 0 } return [math]::Round($d.Free / 1GB, 1) } $sdkRoot = if ((Get-FreeGb 'D') -gt 8) { 'D:\' } else { 'C:\' } $flutterDir = Join-Path $sdkRoot 'flutter' $work = Join-Path $sdkRoot 'oa-build-cache' New-Item -ItemType Directory -Force -Path $work | Out-Null function Test-Flutter { $bat = Join-Path $flutterDir 'bin\flutter.bat' return (Test-Path $bat) } function Ensure-Flutter { if (Test-Flutter) { Write-Host "Flutter already at $flutterDir" return } $zip = Join-Path $work 'flutter_windows_3.27.4-stable.zip' if (-not (Test-Path $zip) -or ((Get-Item $zip).Length -lt 100MB)) { $urls = @( 'https://storage.flutter-io.cn/flutter_infra_release/releases/stable/windows/flutter_windows_3.27.4-stable.zip', 'https://fast-mirror.isrc.ac.cn/flutter/flutter_infra/releases/stable/windows/flutter_windows_3.27.4-stable.zip' ) $ok = $false foreach ($u in $urls) { Write-Host "Downloading Flutter from $u" try { Invoke-WebRequest -Uri $u -OutFile $zip -UseBasicParsing $ok = $true break } catch { Write-Host "download failed: $_" } } if (-not $ok) { throw 'Flutter SDK 下载失败' } } Write-Host "Extracting Flutter to $flutterDir" if (Test-Path $flutterDir) { Remove-Item $flutterDir -Recurse -Force } Expand-Archive -Path $zip -DestinationPath $sdkRoot -Force if (-not (Test-Flutter)) { throw "unzip 后仍没有 $flutterDir\bin\flutter.bat" } } function Ensure-VsBuildTools { $vswhere = "${env:ProgramFiles(x86)}\Microsoft Visual Studio\Installer\vswhere.exe" $ok = $false if (Test-Path $vswhere) { $path = & $vswhere -latest -products * -requires Microsoft.VisualStudio.Component.VC.Tools.x86.x64 -property installationPath if ($path) { $ok = $true } } if ($ok) { Write-Host "VS C++ tools already installed" return } $boot = Join-Path $work 'vs_BuildTools.exe' if (-not (Test-Path $boot)) { Write-Host 'Downloading VS 2022 Build Tools bootstrapper' $urls = @( 'https://aka.ms/vs/17/release/vs_BuildTools.exe' ) $got = $false foreach ($u in $urls) { try { Invoke-WebRequest -Uri $u -OutFile $boot -UseBasicParsing $got = $true break } catch { Write-Host "bootstrapper download failed: $_" } } if (-not $got) { throw 'VS Build Tools 引导程序下载失败' } } $installPath = Join-Path $sdkRoot 'BuildTools' Write-Host "Installing VS Build Tools to $installPath (this takes a while)" $p = Start-Process -FilePath $boot -ArgumentList @( '--quiet', '--wait', '--norestart', '--nocache', '--installPath', $installPath, '--add', 'Microsoft.VisualStudio.Workload.VCTools', '--includeRecommended', '--add', 'Microsoft.VisualStudio.Component.Windows11SDK.22621' ) -Wait -PassThru if ($p.ExitCode -ne 0 -and $p.ExitCode -ne 3010) { throw "VS Build Tools install failed: $($p.ExitCode)" } } function Ensure-Inno { $iscc = @( "${env:ProgramFiles}\Inno Setup 7\ISCC.exe", "${env:ProgramFiles(x86)}\Inno Setup 7\ISCC.exe", "${env:ProgramFiles(x86)}\Inno Setup 6\ISCC.exe", "${env:ProgramFiles}\Inno Setup 6\ISCC.exe" ) | Where-Object { Test-Path $_ } | Select-Object -First 1 if ($iscc) { Write-Host "Inno Setup already at $iscc" return } $setup = Join-Path $work 'innosetup.exe' Write-Host 'Downloading Inno Setup' Invoke-WebRequest -Uri 'https://jrsoftware.org/download.php/is.exe' -OutFile $setup -UseBasicParsing $p = Start-Process -FilePath $setup -ArgumentList '/VERYSILENT','/SUPPRESSMSGBOXES','/NORESTART' -Wait -PassThru if ($p.ExitCode -ne 0) { throw "Inno Setup install failed: $($p.ExitCode)" } } Ensure-Flutter Ensure-VsBuildTools Ensure-Inno Write-Host 'toolchain ready' Write-Host "flutter=$flutterDir\bin\flutter.bat"