- fix(installer): 修复低完整性产物无法写入临时目录的问题,并在 CI 打包前后检查完整性标签 - fix(firmware): 从本次 Cargo ELF 打包并同步配套镜像,修正短目录说明与 LLVM 搜索顺序 - fix(installer): 修复中文完成页和页眉遮挡,侧栏使用等比缩放的原始 Logo - style(client): 应用图标增加圆角,统一“裁判系统客户端”命名 - fix(config): 安装提示改用可选本地热点配置,排除 Wi-Fi 凭据 - docs: 润色项目说明并统一裁判系统术语 - test(packaging): 补充 Windows 完整性和固件打包回归,覆盖外部输出目录、旧镜像与重复生成 验证:Windows NSIS 构建及原生页面预览;通用与本地安装配置编译;固件 release 构建、重复打包和客户端离线校验;6 项固件打包回归与 Windows 权限回归;git diff --check。未执行实机烧录。
102 lines
4.9 KiB
PowerShell
102 lines
4.9 KiB
PowerShell
# Build the ESP32-S3 firmware from PowerShell without executing .env as code.
|
||
[CmdletBinding()]
|
||
param(
|
||
[string]$EnvFile = '.env',
|
||
[switch]$Package,
|
||
[Parameter(ValueFromRemainingArguments = $true)]
|
||
[string[]]$CargoArgs = @()
|
||
)
|
||
|
||
$ErrorActionPreference = 'Stop'
|
||
Set-StrictMode -Version Latest
|
||
Push-Location (Split-Path -Parent $PSScriptRoot)
|
||
$buildEnvironment = @{}
|
||
foreach ($name in @('CARGO_WORKSPACE_DIR', 'ESP_IDF_GLOB_BASE', 'ESP_IDF_GLOB_PARTITIONS')) {
|
||
$buildEnvironment[$name] = [Environment]::GetEnvironmentVariable($name, 'Process')
|
||
}
|
||
try {
|
||
if (Test-Path -LiteralPath $EnvFile) {
|
||
$lineNumber = 0
|
||
foreach ($line in Get-Content -LiteralPath $EnvFile -Encoding UTF8) {
|
||
$lineNumber++
|
||
if ($line -match '^\s*(#|$)') { continue }
|
||
if ($line -notmatch '^\s*(?:export\s+)?([A-Za-z_][A-Za-z0-9_]*)\s*=(.*)$') {
|
||
throw "Invalid assignment in ${EnvFile}:${lineNumber}"
|
||
}
|
||
$key = $Matches[1]
|
||
$value = $Matches[2].Trim()
|
||
if ($value.StartsWith("'") -or $value.StartsWith('"')) {
|
||
$quote = $value.Substring(0, 1)
|
||
if ($value.Length -lt 2 -or -not $value.EndsWith($quote)) {
|
||
throw "Unclosed quote in ${EnvFile}:${lineNumber}"
|
||
}
|
||
$value = $value.Substring(1, $value.Length - 2)
|
||
} else {
|
||
$value = ($value -replace '\s+#.*$', '').TrimEnd()
|
||
}
|
||
[Environment]::SetEnvironmentVariable($key, $value, 'Process')
|
||
}
|
||
}
|
||
|
||
if ([string]::IsNullOrWhiteSpace($env:WIFI_SSID) -or $env:WIFI_SSID -eq 'your-ssid') {
|
||
throw 'Set WIFI_SSID in .env (copy .env.example) or the environment before building.'
|
||
}
|
||
if ($null -eq $env:WIFI_PASS) { $env:WIFI_PASS = '' }
|
||
|
||
# bindgen 要加载 esp-clang 自带的 libclang.dll,而它依赖**同目录**的 libLLVM-21.dll、
|
||
# libclang-cpp.dll 等。LoadLibraryEx 默认不会去 DLL 自己的目录找依赖,所以必须把这个
|
||
# 目录放进 PATH,否则报的是一句毫不相干的话:
|
||
# Unable to find libclang: "...\libclang.dll could not be opened: LoadLibraryExW failed"
|
||
# (`espup` 的 shell 会替你导出这些变量,直接跑脚本的人不会。)
|
||
$espClang = Join-Path $env:USERPROFILE '.rustup\toolchains\esp-1.97.0.0\xtensa-esp32-elf-clang\esp-clang\bin'
|
||
if (Test-Path -LiteralPath (Join-Path $espClang 'libclang.dll')) {
|
||
$env:LIBCLANG_PATH = $espClang
|
||
# An existing entry can be behind another LLVM installation. Move it
|
||
# to the front so libclang-cpp.dll and the runtime match libclang.dll.
|
||
$otherPaths = @($env:PATH -split ';' | Where-Object { $_ -ne $espClang })
|
||
$env:PATH = (@($espClang) + $otherPaths) -join ';'
|
||
}
|
||
|
||
$env:CARGO_WORKSPACE_DIR = (Get-Location).Path
|
||
$env:ESP_IDF_GLOB_BASE = (Get-Location).Path
|
||
$env:ESP_IDF_GLOB_PARTITIONS = 'partitions.csv'
|
||
|
||
$firmwareElf = $null
|
||
if ($Package) {
|
||
# Use Cargo's actual artifact path, including --target-dir / --config
|
||
# overrides, rather than guessing where this build wrote its ELF.
|
||
& cargo build --release --locked --message-format=json-render-diagnostics @CargoArgs | ForEach-Object {
|
||
$message = $_ | ConvertFrom-Json
|
||
if ($message.reason -eq 'compiler-artifact' -and $message.target.name -eq 'esp32' -and $message.executable) {
|
||
$firmwareElf = $message.executable
|
||
}
|
||
}
|
||
} else {
|
||
& cargo build --release --locked @CargoArgs
|
||
}
|
||
if ($LASTEXITCODE -ne 0) { throw "cargo build failed (exit $LASTEXITCODE)." }
|
||
|
||
if ($Package) {
|
||
if (-not $firmwareElf) { throw 'Cargo did not report the esp32 firmware ELF; refusing to package old images.' }
|
||
$python = Get-Command python -ErrorAction SilentlyContinue
|
||
if ($null -eq $python) {
|
||
throw '-Package requires Python 3 on PATH (used by scripts/package_firmware.py).'
|
||
}
|
||
# 固件包的版本号与客户端同源:都读仓库根的 version.json(由 scripts/version.mjs
|
||
# 从 git 历史算出)。不传的话 make_bundle.py 会退回 BUILD-INFO.json 里的
|
||
# 变体名+提交号,那是另一套编号,装到客户端里会与界面上的版本对不上。
|
||
$versionArgs = @()
|
||
if (Test-Path -LiteralPath 'version.json') {
|
||
$info = Get-Content -LiteralPath 'version.json' -Raw | ConvertFrom-Json
|
||
$versionArgs = @('--version', "v$($info.version)+$($info.build)")
|
||
}
|
||
& python scripts/package_firmware.py --firmware target/firmware --elf $firmwareElf --name 'RMIC 图传固件' @versionArgs
|
||
if ($LASTEXITCODE -ne 0) { throw "package_firmware.py failed (exit $LASTEXITCODE)." }
|
||
}
|
||
} finally {
|
||
foreach ($name in $buildEnvironment.Keys) {
|
||
[Environment]::SetEnvironmentVariable($name, $buildEnvironment[$name], 'Process')
|
||
}
|
||
Pop-Location
|
||
}
|