visionA/local-tool/scripts/bootstrap-windows.ps1
jim800121chen e6f7afe8db fix(local-tool): 強化 Inno Setup 偵測,支援 ISCC 環境變數 override
Makefile (exe target):
- 新增 ISCC 環境變數 override(絕對路徑優先)
- 偵測順序:\$ISCC → command -v iscc → 已知絕對路徑
- 找不到時列出已嘗試路徑方便 debug

bootstrap-windows.ps1:
- Find-Iscc 函數改用多層策略:固定路徑 → 登錄檔 InstallLocation → Program Files 遞迴掃描
- 偵測不到就自動 winget --force 重裝再試一次
- 同時 export PATH 和 ISCC 雙保險傳給 Makefile

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-12 02:27:38 +08:00

188 lines
6.7 KiB
PowerShell
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# visionA-local — Windows 10/11 x86_64 一鍵 build
#
# 使用方式PowerShell 以「系統管理員」開啟):
# git clone https://github.com/jim800121/visionA.git
# cd visionA\local-tool
# powershell -ExecutionPolicy Bypass -File scripts\bootstrap-windows.ps1
#
# 環境變數:
# $env:VISIONA_TARGET 預設 exe可設 wails-windows / payload-windows
$ErrorActionPreference = 'Stop'
$Target = if ($env:VISIONA_TARGET) { $env:VISIONA_TARGET } else { 'exe' }
function Log($msg) { Write-Host "==> $msg" -ForegroundColor Cyan }
function Fail($msg) { Write-Host "!!! $msg" -ForegroundColor Red; exit 1 }
# 必須以系統管理員身份執行winget 需要)
$isAdmin = ([Security.Principal.WindowsPrincipal] `
[Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole(
[Security.Principal.WindowsBuiltInRole] 'Administrator')
if (-not $isAdmin) { Fail '請以系統管理員身份執行 PowerShell 再跑此腳本' }
if (-not (Test-Path 'Makefile') -or -not (Test-Path 'visiona-local')) {
Fail '請先 cd 到 local-tool\ 目錄再執行此腳本'
}
if (-not (Get-Command winget -ErrorAction SilentlyContinue)) {
Fail 'winget 未安裝。請先從 Microsoft Store 安裝「App Installer」'
}
function Ensure-Winget($id) {
$installed = winget list --id $id -e 2>$null | Select-String $id
if (-not $installed) {
Log "安裝 $id"
winget install -e --id $id --accept-source-agreements --accept-package-agreements
} else {
Log "$id 已安裝,跳過"
}
}
Log '[1/4] 安裝系統套件'
Ensure-Winget 'Git.Git'
Ensure-Winget 'GoLang.Go'
Ensure-Winget 'OpenJS.NodeJS.LTS'
Ensure-Winget 'Python.Python.3.12'
Ensure-Winget 'JRSoftware.InnoSetup'
Ensure-Winget 'MSYS2.MSYS2'
# 重新載入 PATHwinget 裝完目前 session 拿不到)
$env:Path = [System.Environment]::GetEnvironmentVariable('Path','Machine') + ';' + `
[System.Environment]::GetEnvironmentVariable('Path','User')
$env:Path += ";$HOME\go\bin;C:\msys64\usr\bin;C:\msys64\mingw64\bin"
Log '[2/4] 安裝 pnpm'
if (-not (Get-Command pnpm -ErrorAction SilentlyContinue)) {
npm i -g pnpm
}
Log '[3/4] 安裝 Wails CLI + 確認 MSYS2 make'
if (-not (Get-Command wails -ErrorAction SilentlyContinue)) {
go install github.com/wailsapp/wails/v2/cmd/wails@latest
}
wails doctor
if (-not (Test-Path 'C:\msys64\usr\bin\make.exe')) {
Log '安裝 MSYS2 make'
& 'C:\msys64\usr\bin\bash.exe' -lc 'pacman -Sy --noconfirm make'
}
Log "[4/4] 開始 buildtarget=$Target"
Log '⚠️ ffmpeg 使用 GPL build需設定 VISIONA_ALLOW_GPL_FFMPEG=1'
# 讓 MSYS2 bash 繼承 Windows PATH才找得到 go / pnpm / python / wails
$env:MSYS2_PATH_TYPE = 'inherit'
$env:CHERE_INVOKING = '1'
# 找真實的 Python避開 Microsoft Store 的 WindowsApps stub
$realPython = $null
$pyCandidates = @(
"$env:LOCALAPPDATA\Programs\Python\Python312\python.exe",
"$env:LOCALAPPDATA\Programs\Python\Python313\python.exe",
"$env:ProgramFiles\Python312\python.exe",
"$env:ProgramFiles\Python313\python.exe"
)
foreach ($p in $pyCandidates) {
if (Test-Path $p) { $realPython = $p; break }
}
if (-not $realPython) {
# 試 py launcher
$pyLauncher = Get-Command py -ErrorAction SilentlyContinue
if ($pyLauncher) { $realPython = 'py -3' }
}
if (-not $realPython) {
Fail '找不到真實 Pythonwinget 可能沒裝成功,或 PATH 沒更新)。請重開 PowerShell 再試一次'
}
Log "偵測到 Python: $realPython"
# 把 Windows 路徑轉成 MSYS2 bash 能吃的格式
function Convert-ToMsysPath($winPath) {
if ($winPath -match '^[A-Za-z]:\\') {
return '/' + $winPath.Substring(0,1).ToLower() + '/' + ($winPath.Substring(3) -replace '\\','/')
}
return $winPath
}
$msysPython = Convert-ToMsysPath $realPython
# 找 Inno Setup Compiler (ISCC.exe)
# 重要:檔名是 ISCC.exe大寫winget 裝在 Program Files (x86) 不在 PATH 裡
function Find-Iscc {
$candidates = @(
"${env:ProgramFiles(x86)}\Inno Setup 6\ISCC.exe",
"$env:ProgramFiles\Inno Setup 6\ISCC.exe",
"${env:ProgramFiles(x86)}\Inno Setup 5\ISCC.exe"
)
foreach ($p in $candidates) {
if ($p -and (Test-Path $p)) { return $p }
}
# 從登錄檔找 Inno Setup 的安裝路徑
$regPaths = @(
'HKLM:\SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall\Inno Setup 6_is1',
'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\Inno Setup 6_is1'
)
foreach ($rp in $regPaths) {
$item = Get-ItemProperty $rp -ErrorAction SilentlyContinue
if ($item -and $item.InstallLocation) {
$p = Join-Path $item.InstallLocation 'ISCC.exe'
if (Test-Path $p) { return $p }
}
}
# 最後備案:掃 Program Files 底下
$found = Get-ChildItem -Path "${env:ProgramFiles(x86)}","$env:ProgramFiles" `
-Filter 'ISCC.exe' -Recurse -ErrorAction SilentlyContinue -Force |
Select-Object -First 1
if ($found) { return $found.FullName }
return $null
}
$isccPath = Find-Iscc
if (-not $isccPath) {
Log 'Inno Setup 偵測不到,用 winget 重裝一次'
winget install -e --id JRSoftware.InnoSetup --accept-source-agreements --accept-package-agreements --force
$isccPath = Find-Iscc
}
if ($isccPath) {
Log "偵測到 Inno Setup: $isccPath"
$msysIsccDir = Convert-ToMsysPath (Split-Path $isccPath -Parent)
$msysIsccExe = Convert-ToMsysPath $isccPath
} else {
Log 'WARN: 仍然找不到 Inno Setupiscc.exemake exe 步驟會失敗'
$msysIsccDir = $null
$msysIsccExe = $null
}
# Makefile 需要 bash + make透過 MSYS2 bash 執行
# 將 Windows 路徑 C:\foo\bar 轉成 MSYS2 路徑 /c/foo/bar
$projectPath = (Get-Location).Path
$msysPath = '/' + $projectPath.Substring(0,1).ToLower() + '/' + `
($projectPath.Substring(3) -replace '\\','/')
$bashParts = @(
"cd '$msysPath'",
'export VISIONA_ALLOW_GPL_FFMPEG=1',
"export VISIONA_PYTHON='$msysPython'"
)
if ($msysIsccDir) {
$bashParts += "export PATH=`"$msysIsccDir`":`$PATH"
}
if ($msysIsccExe) {
$bashParts += "export ISCC=`"$msysIsccExe`""
}
$bashParts += 'make vendor-python-windows vendor-wheels-windows vendor-ffmpeg-windows vendor-ytdlp-windows'
$bashParts += 'make payload-windows'
switch ($Target) {
'payload-windows' { }
'wails-windows' { $bashParts += 'make wails-windows' }
default { $bashParts += 'make wails-windows'; $bashParts += 'make exe' }
}
$bashCmd = $bashParts -join ' && '
& 'C:\msys64\usr\bin\bash.exe' -lc $bashCmd
if ($LASTEXITCODE -ne 0) { Fail "build 失敗exit code=$LASTEXITCODE" }
Log '完成 ✅'
Log "產出位置:$(Join-Path (Get-Location) 'dist')"
Get-ChildItem dist -ErrorAction SilentlyContinue | Format-Table Name, Length