mirror of
https://github.com/NanmiCoder/cc-haha
synced 2026-07-16 13:03:31 +08:00
- Windows 上隐藏原生菜单栏和窗口装饰,前端渲染自定义窗口控制按钮(最小化/最大化/关闭) - macOS 保持原生菜单栏不变(条件编译) - Sidebar 在 Windows 上不再添加 macOS 红绿灯的额外顶部间距 - 新增 Windows 构建脚本和 NSIS 安装钩子 - 服务端 CORS、会话服务、对话服务改进及测试补充 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
296 lines
8.2 KiB
PowerShell
296 lines
8.2 KiB
PowerShell
[CmdletBinding()]
|
|
param(
|
|
[Parameter(ValueFromRemainingArguments = $true)]
|
|
[string[]]$TauriArgs
|
|
)
|
|
|
|
$ErrorActionPreference = 'Stop'
|
|
Set-StrictMode -Version Latest
|
|
|
|
$scriptDir = Split-Path -Parent $MyInvocation.MyCommand.Path
|
|
$desktopDir = (Resolve-Path (Join-Path $scriptDir '..')).Path
|
|
$repoRoot = (Resolve-Path (Join-Path $desktopDir '..')).Path
|
|
|
|
$targetTriple = 'x86_64-pc-windows-msvc'
|
|
$tauriTargetDir = Join-Path $desktopDir 'src-tauri\target'
|
|
$canonicalOutputDir = Join-Path $desktopDir 'build-artifacts\windows-x64'
|
|
$activeOutputDir = $canonicalOutputDir
|
|
|
|
function Write-Step {
|
|
param([string]$Message)
|
|
Write-Host "[build-windows-x64] $Message"
|
|
}
|
|
|
|
function Assert-WindowsHost {
|
|
if ($env:OS -ne 'Windows_NT') {
|
|
throw '[build-windows-x64] This script must run on Windows.'
|
|
}
|
|
}
|
|
|
|
function Assert-Command {
|
|
param([string]$Name)
|
|
|
|
if (-not (Get-Command $Name -ErrorAction SilentlyContinue)) {
|
|
throw "[build-windows-x64] Missing required command: $Name"
|
|
}
|
|
}
|
|
|
|
function Import-VsDevEnvironment {
|
|
$vswhere = 'C:\Program Files (x86)\Microsoft Visual Studio\Installer\vswhere.exe'
|
|
if (-not (Test-Path $vswhere)) {
|
|
throw '[build-windows-x64] Could not find vswhere.exe. Install Visual Studio 2022 Build Tools with the C++ workload.'
|
|
}
|
|
|
|
$installationPath = & $vswhere `
|
|
-products * `
|
|
-requires Microsoft.VisualStudio.Component.VC.Tools.x86.x64 `
|
|
-property installationPath |
|
|
Select-Object -First 1
|
|
|
|
if (-not $installationPath) {
|
|
throw '[build-windows-x64] Missing Visual C++ build tools. Install the "Desktop development with C++" / VC.Tools.x86.x64 workload first.'
|
|
}
|
|
|
|
$vsDevCmd = Join-Path $installationPath 'Common7\Tools\VsDevCmd.bat'
|
|
if (-not (Test-Path $vsDevCmd)) {
|
|
throw "[build-windows-x64] Could not find VsDevCmd.bat under $installationPath"
|
|
}
|
|
|
|
Write-Step "Importing MSVC environment from $vsDevCmd"
|
|
|
|
$env:VSCMD_SKIP_SENDTELEMETRY = '1'
|
|
$envDump = & cmd.exe /d /s /c "`"$vsDevCmd`" -arch=x64 -host_arch=x64 >nul && set"
|
|
if ($LASTEXITCODE -ne 0) {
|
|
throw "[build-windows-x64] Failed to initialize Visual Studio build environment (exit $LASTEXITCODE)"
|
|
}
|
|
|
|
foreach ($line in $envDump) {
|
|
if ($line -match '^(.*?)=(.*)$') {
|
|
[Environment]::SetEnvironmentVariable($matches[1], $matches[2], 'Process')
|
|
}
|
|
}
|
|
}
|
|
|
|
function Get-RustCargoBinDir {
|
|
return Join-Path $env:USERPROFILE '.cargo\bin'
|
|
}
|
|
|
|
function Ensure-RustInPath {
|
|
$cargoBinDir = Get-RustCargoBinDir
|
|
if ((Test-Path $cargoBinDir) -and -not (($env:Path -split ';') -contains $cargoBinDir)) {
|
|
$env:Path = "$cargoBinDir;$env:Path"
|
|
}
|
|
}
|
|
|
|
function Get-LatestArtifact {
|
|
param(
|
|
[string[]]$SearchRoots,
|
|
[string[]]$Patterns
|
|
)
|
|
|
|
foreach ($root in $SearchRoots) {
|
|
if (-not (Test-Path $root)) {
|
|
continue
|
|
}
|
|
|
|
foreach ($pattern in $Patterns) {
|
|
$match = Get-ChildItem -Path $root -File -Filter $pattern -ErrorAction SilentlyContinue |
|
|
Sort-Object Name |
|
|
Select-Object -Last 1
|
|
|
|
if ($match) {
|
|
return $match
|
|
}
|
|
}
|
|
}
|
|
|
|
return $null
|
|
}
|
|
|
|
function Resolve-OutputDirectory {
|
|
param([string]$PreferredPath)
|
|
|
|
New-Item -ItemType Directory -Force -Path $PreferredPath | Out-Null
|
|
|
|
$existingArtifacts = Get-ChildItem -Path $PreferredPath -Force -ErrorAction SilentlyContinue
|
|
foreach ($artifact in $existingArtifacts) {
|
|
try {
|
|
Remove-Item -LiteralPath $artifact.FullName -Force -Recurse
|
|
} catch {
|
|
$fallbackPath = "$PreferredPath-$(Get-Date -Format 'yyyyMMdd-HHmmss')"
|
|
Write-Step "Could not clear locked artifact '$($artifact.FullName)'. Using fallback output directory: $fallbackPath"
|
|
New-Item -ItemType Directory -Force -Path $fallbackPath | Out-Null
|
|
return $fallbackPath
|
|
}
|
|
}
|
|
|
|
return $PreferredPath
|
|
}
|
|
|
|
Assert-WindowsHost
|
|
Assert-Command bun
|
|
|
|
Ensure-RustInPath
|
|
Import-VsDevEnvironment
|
|
|
|
Assert-Command cargo
|
|
Assert-Command rustc
|
|
Assert-Command bunx
|
|
|
|
if ($env:SKIP_INSTALL -ne '1') {
|
|
Write-Step 'Installing root dependencies...'
|
|
Push-Location $repoRoot
|
|
try {
|
|
& bun install
|
|
if ($LASTEXITCODE -ne 0) {
|
|
throw "[build-windows-x64] bun install failed in repo root (exit $LASTEXITCODE)"
|
|
}
|
|
} finally {
|
|
Pop-Location
|
|
}
|
|
|
|
Write-Step 'Installing desktop dependencies...'
|
|
Push-Location $desktopDir
|
|
try {
|
|
& bun install
|
|
if ($LASTEXITCODE -ne 0) {
|
|
throw "[build-windows-x64] bun install failed in desktop (exit $LASTEXITCODE)"
|
|
}
|
|
} finally {
|
|
Pop-Location
|
|
}
|
|
|
|
$adaptersDir = Join-Path $repoRoot 'adapters'
|
|
if (Test-Path (Join-Path $adaptersDir 'package.json')) {
|
|
Write-Step 'Installing adapter dependencies...'
|
|
Push-Location $adaptersDir
|
|
try {
|
|
& bun install
|
|
if ($LASTEXITCODE -ne 0) {
|
|
throw "[build-windows-x64] bun install failed in adapters (exit $LASTEXITCODE)"
|
|
}
|
|
} finally {
|
|
Pop-Location
|
|
}
|
|
}
|
|
}
|
|
|
|
$tauriBuildArgs = @(
|
|
'tauri',
|
|
'build',
|
|
'--target',
|
|
$targetTriple,
|
|
'--bundles',
|
|
'nsis,msi',
|
|
'--ci'
|
|
)
|
|
|
|
$tempConfigPath = $null
|
|
if (-not $env:TAURI_SIGNING_PRIVATE_KEY) {
|
|
$tempConfigPath = Join-Path ([System.IO.Path]::GetTempPath()) 'cc-haha.tauri.local.windows.json'
|
|
$tempConfig = @{
|
|
bundle = @{
|
|
createUpdaterArtifacts = $false
|
|
}
|
|
} | ConvertTo-Json -Depth 10
|
|
Set-Content -Path $tempConfigPath -Value $tempConfig -Encoding UTF8
|
|
Write-Step 'TAURI_SIGNING_PRIVATE_KEY not set, disabling updater artifacts for local build'
|
|
$tauriBuildArgs += @('--config', $tempConfigPath)
|
|
}
|
|
|
|
if ($null -ne $TauriArgs) {
|
|
$remainingArgs = @($TauriArgs)
|
|
if ($remainingArgs.Count -gt 0) {
|
|
$tauriBuildArgs += $remainingArgs
|
|
}
|
|
}
|
|
|
|
Write-Step "Building Windows desktop app for $targetTriple"
|
|
|
|
Push-Location $desktopDir
|
|
try {
|
|
$env:TAURI_ENV_TARGET_TRIPLE = $targetTriple
|
|
& bunx @tauriBuildArgs
|
|
if ($LASTEXITCODE -ne 0) {
|
|
throw "[build-windows-x64] tauri build failed (exit $LASTEXITCODE)"
|
|
}
|
|
} finally {
|
|
Pop-Location
|
|
if ($tempConfigPath -and (Test-Path $tempConfigPath)) {
|
|
Remove-Item -LiteralPath $tempConfigPath -Force
|
|
}
|
|
}
|
|
|
|
$activeOutputDir = Resolve-OutputDirectory -PreferredPath $canonicalOutputDir
|
|
|
|
$bundleRoots = @(
|
|
(Join-Path $tauriTargetDir "$targetTriple\release\bundle"),
|
|
(Join-Path $tauriTargetDir 'release\bundle')
|
|
)
|
|
|
|
$artifactPatterns = @('*.exe', '*.msi', '*.zip', '*.sig', 'latest.json')
|
|
$copiedArtifacts = New-Object System.Collections.Generic.List[string]
|
|
|
|
foreach ($root in $bundleRoots) {
|
|
if (-not (Test-Path $root)) {
|
|
continue
|
|
}
|
|
|
|
foreach ($pattern in $artifactPatterns) {
|
|
$artifacts = Get-ChildItem -Path $root -Recurse -File -Filter $pattern -ErrorAction SilentlyContinue
|
|
foreach ($artifact in $artifacts) {
|
|
$destination = Join-Path $activeOutputDir $artifact.Name
|
|
Copy-Item -LiteralPath $artifact.FullName -Destination $destination -Force
|
|
if (-not $copiedArtifacts.Contains($destination)) {
|
|
$copiedArtifacts.Add($destination) | Out-Null
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
$nsisInstaller = Get-LatestArtifact -SearchRoots @(
|
|
(Join-Path $tauriTargetDir "$targetTriple\release\bundle\nsis"),
|
|
(Join-Path $tauriTargetDir 'release\bundle\nsis')
|
|
) -Patterns @('*.exe')
|
|
|
|
$msiInstaller = Get-LatestArtifact -SearchRoots @(
|
|
(Join-Path $tauriTargetDir "$targetTriple\release\bundle\msi"),
|
|
(Join-Path $tauriTargetDir 'release\bundle\msi')
|
|
) -Patterns @('*.msi')
|
|
|
|
$nsisInstallerPath = if ($nsisInstaller) { $nsisInstaller.FullName } else { 'not found' }
|
|
$msiInstallerPath = if ($msiInstaller) { $msiInstaller.FullName } else { 'not found' }
|
|
|
|
$buildInfo = @(
|
|
"Target triple: $targetTriple"
|
|
"Canonical output: $canonicalOutputDir"
|
|
"Actual output: $activeOutputDir"
|
|
"NSIS installer: $nsisInstallerPath"
|
|
"MSI installer: $msiInstallerPath"
|
|
"Artifacts copied: $($copiedArtifacts.Count)"
|
|
"Built at: $(Get-Date -Format 'yyyy-MM-dd HH:mm:ss zzz')"
|
|
)
|
|
|
|
Set-Content -Path (Join-Path $activeOutputDir 'BUILD_INFO.txt') -Value $buildInfo -Encoding UTF8
|
|
|
|
Write-Host ''
|
|
Write-Step 'Build finished.'
|
|
Write-Step "Artifacts output: $activeOutputDir"
|
|
if ($nsisInstaller) {
|
|
Write-Step "NSIS installer source: $($nsisInstaller.FullName)"
|
|
} else {
|
|
Write-Step 'No NSIS installer found under bundle directories.'
|
|
}
|
|
|
|
if ($msiInstaller) {
|
|
Write-Step "MSI installer source: $($msiInstaller.FullName)"
|
|
} else {
|
|
Write-Step 'No MSI installer found under bundle directories.'
|
|
}
|
|
|
|
Write-Step "Canonical output: $canonicalOutputDir"
|
|
|
|
if ($env:OPEN_OUTPUT -eq '1') {
|
|
Invoke-Item $canonicalOutputDir
|
|
}
|