Files
banban/factory_host/scripts/build_release.ps1

142 lines
6.3 KiB
PowerShell

param(
[string]$Output = "dist",
[string]$FactoryFirmware = "",
[string]$OfficialFirmware = ""
)
$ErrorActionPreference = "Stop"
$scriptRoot = Split-Path -Parent $MyInvocation.MyCommand.Path
$factoryHostRoot = Split-Path -Parent $scriptRoot
$projectRoot = Split-Path -Parent $factoryHostRoot
$buildRoot = Join-Path $factoryHostRoot "build"
function Resolve-ProjectInput([string]$Value, [string]$DefaultRelativePath) {
$selected = if ([string]::IsNullOrWhiteSpace($Value)) { $DefaultRelativePath } else { $Value }
if ([System.IO.Path]::IsPathRooted($selected)) {
return [System.IO.Path]::GetFullPath($selected)
}
return [System.IO.Path]::GetFullPath((Join-Path $projectRoot $selected))
}
$outputCandidate = if ([System.IO.Path]::IsPathRooted($Output)) {
$Output
} else {
Join-Path $factoryHostRoot $Output
}
$outDir = [System.IO.Path]::GetFullPath($outputCandidate)
$factoryHostPrefix = [System.IO.Path]::GetFullPath($factoryHostRoot).TrimEnd("\") + "\"
if (-not $outDir.StartsWith($factoryHostPrefix, [System.StringComparison]::OrdinalIgnoreCase)) {
throw "Output 必须位于 factory_host 目录内: $outDir"
}
$pyinstallerDist = Join-Path $buildRoot "pyinstaller-dist"
$pyinstallerWork = Join-Path $buildRoot "pyinstaller-work"
$pyinstallerSpec = Join-Path $buildRoot "pyinstaller-spec"
$buildExe = Join-Path $pyinstallerDist "EG800FactoryHost.exe"
$releaseExe = Join-Path $outDir "START-EG800-FACTORY-TOOL.exe"
$runtimeDir = Join-Path $outDir ".runtime"
$firmwareDir = Join-Path $outDir "firmware"
$toolSource = Join-Path $factoryHostRoot "vendor\aboot-tools-2024.08.08-win-x64"
$toolDestination = Join-Path $runtimeDir "burn_tool\aboot-tools-2024.08.08-win-x64"
$factoryFirmwareSource = Resolve-ProjectInput $FactoryFirmware "factory_host\firmware\test\EG800AKCN_11LG-FT1-factory-test.zip"
$officialFirmwareSource = Resolve-ProjectInput $OfficialFirmware "factory_host\firmware\official\EG800AKCN_11LG-official-fac.zip"
$factoryFirmwareDestination = Join-Path $firmwareDir "EG800AKCN_11LG-FT1-factory-test.zip"
$officialFirmwareDestination = Join-Path $firmwareDir "EG800AKCN_11LG-official-fac.zip"
$releaseZip = Join-Path $outDir "EG800-Factory-Tool-Full-Package.zip"
python -c "import PyInstaller" 2>$null
if ($LASTEXITCODE -ne 0) {
throw "未找到 PyInstaller。先执行: python -m pip install pyinstaller pyserial"
}
foreach ($required in @($toolSource, $factoryFirmwareSource, $officialFirmwareSource)) {
if (-not (Test-Path -LiteralPath $required)) {
throw "发布所需文件不存在: $required"
}
}
# dist is disposable. Source and intermediate artifacts live elsewhere.
New-Item -ItemType Directory -Force -Path $outDir, $buildRoot | Out-Null
Get-ChildItem -LiteralPath $outDir -Force | Remove-Item -Recurse -Force
if (Test-Path -LiteralPath $pyinstallerDist) {
Remove-Item -LiteralPath $pyinstallerDist -Recurse -Force
}
python -m PyInstaller --noconfirm --clean --onefile --windowed `
--name EG800FactoryHost `
--distpath $pyinstallerDist `
--workpath $pyinstallerWork `
--specpath $pyinstallerSpec `
(Join-Path $factoryHostRoot "src\factory_host.py")
if ($LASTEXITCODE -ne 0 -or -not (Test-Path -LiteralPath $buildExe)) {
throw "PyInstaller 构建失败,退出码: $LASTEXITCODE"
}
New-Item -ItemType Directory -Force -Path $runtimeDir, $firmwareDir | Out-Null
Move-Item -LiteralPath $buildExe -Destination $releaseExe -Force
Copy-Item -LiteralPath (Join-Path $factoryHostRoot "config\factory_host_config.json") `
-Destination (Join-Path $runtimeDir "factory_host_config.json") -Force
Copy-Item -LiteralPath $toolSource -Destination $toolDestination -Recurse -Force
Copy-Item -LiteralPath $factoryFirmwareSource -Destination $factoryFirmwareDestination -Force
Copy-Item -LiteralPath $officialFirmwareSource -Destination $officialFirmwareDestination -Force
New-Item -ItemType Directory -Force -Path `
(Join-Path $runtimeDir "docs"), (Join-Path $runtimeDir "logs") | Out-Null
Copy-Item -LiteralPath (Join-Path $factoryHostRoot "docs\USAGE.md") `
-Destination (Join-Path $runtimeDir "docs\USAGE.md") -Force
$revision = ""
try {
$revisionOutput = & git -C $projectRoot rev-parse HEAD 2>$null
if ($LASTEXITCODE -eq 0 -and $revisionOutput) {
$revision = ($revisionOutput | Select-Object -First 1).Trim()
}
} catch {
$revision = ""
}
$manifest = [ordered]@{
format = "eg800-factory-host-release-v1"
generated_at = (Get-Date).ToUniversalTime().ToString("o")
git_revision = $revision
files = [ordered]@{
executable = [ordered]@{
path = "START-EG800-FACTORY-TOOL.exe"
bytes = (Get-Item -LiteralPath $releaseExe).Length
sha256 = (Get-FileHash -LiteralPath $releaseExe -Algorithm SHA256).Hash
}
factory_firmware = [ordered]@{
path = "firmware/EG800AKCN_11LG-FT1-factory-test.zip"
bytes = (Get-Item -LiteralPath $factoryFirmwareDestination).Length
sha256 = (Get-FileHash -LiteralPath $factoryFirmwareDestination -Algorithm SHA256).Hash
}
official_firmware = [ordered]@{
path = "firmware/EG800AKCN_11LG-official-fac.zip"
bytes = (Get-Item -LiteralPath $officialFirmwareDestination).Length
sha256 = (Get-FileHash -LiteralPath $officialFirmwareDestination -Algorithm SHA256).Hash
}
downloader = [ordered]@{
path = ".runtime/burn_tool/aboot-tools-2024.08.08-win-x64/adownload.exe"
bytes = (Get-Item -LiteralPath (Join-Path $toolDestination "adownload.exe")).Length
sha256 = (Get-FileHash -LiteralPath (Join-Path $toolDestination "adownload.exe") -Algorithm SHA256).Hash
}
}
}
$manifest | ConvertTo-Json -Depth 5 | Set-Content `
-LiteralPath (Join-Path $runtimeDir "release_manifest.json") -Encoding UTF8
$runtimeItem = Get-Item -LiteralPath $runtimeDir -Force
$runtimeItem.Attributes = $runtimeItem.Attributes -bor [System.IO.FileAttributes]::Hidden
Push-Location $outDir
try {
& tar.exe -a -c -f $releaseZip "START-EG800-FACTORY-TOOL.exe" "firmware" ".runtime"
if ($LASTEXITCODE -ne 0) {
throw "tar.exe 创建完整交付包失败,退出码: $LASTEXITCODE"
}
} finally {
Pop-Location
}
Write-Host "发布目录: $outDir"
Write-Host "上位机: $releaseExe"
Write-Host "完整交付包: $releaseZip"
Write-Host "SHA256: $((Get-FileHash -LiteralPath $releaseZip -Algorithm SHA256).Hash)"