[CmdletBinding()] param( [string]$OutputName = 'integrated_platform-win64' ) Set-StrictMode -Version Latest $ErrorActionPreference = 'Stop' $projectRoot = Split-Path -Parent $PSScriptRoot $qtRoot = if ($env:QTDIR) { $env:QTDIR } else { 'D:\Qt5.15.2\5.15.2\mingw81_64' } $mingwBin = 'D:\Qt5.15.2\Tools\mingw810_64\bin' $qmakePath = Join-Path $qtRoot 'bin\qmake.exe' $makePath = Join-Path $mingwBin 'mingw32-make.exe' $pluginDirectory = Join-Path $qtRoot 'plugins' $platformPlugin = Join-Path $pluginDirectory 'platforms\qwindows.dll' $stylePlugin = Join-Path $pluginDirectory 'styles\qwindowsvistastyle.dll' $qtProjectFile = Join-Path $projectRoot 'app\integrated_platform.pro' $runtimeBuildRoot = Join-Path $projectRoot 'build\runtime-export' $buildDirectory = Join-Path $runtimeBuildRoot ([guid]::NewGuid().ToString('N')) $executablePath = Join-Path $buildDirectory 'release\integrated_platform.exe' $packageRoot = Join-Path $projectRoot 'build\package' foreach ($requiredPath in @($qmakePath, $makePath, $platformPlugin, $stylePlugin, $qtProjectFile)) { if (-not (Test-Path -LiteralPath $requiredPath)) { throw "未找到必要文件:$requiredPath" } } if ([string]::IsNullOrWhiteSpace($OutputName) -or $OutputName -in @('.', '..') -or $OutputName.IndexOfAny([System.IO.Path]::GetInvalidFileNameChars()) -ge 0 -or [System.IO.Path]::GetFileName($OutputName) -ne $OutputName) { throw "输出名称不是有效的 Windows 文件名:$OutputName" } $packageDirectory = Join-Path $packageRoot $OutputName $archivePath = Join-Path $packageRoot "$OutputName.zip" $resolvedProjectRoot = [System.IO.Path]::GetFullPath($projectRoot).TrimEnd('\') $resolvedPackageRoot = [System.IO.Path]::GetFullPath($packageRoot).TrimEnd('\') $resolvedPackageDirectory = [System.IO.Path]::GetFullPath($packageDirectory) if (-not $resolvedPackageRoot.StartsWith("$resolvedProjectRoot\build\", [System.StringComparison]::OrdinalIgnoreCase) -or [System.IO.Path]::GetDirectoryName($resolvedPackageDirectory) -ne $resolvedPackageRoot) { throw "打包目录必须是 build\package 的直接子目录:$resolvedPackageDirectory" } New-Item -ItemType Directory -Path $buildDirectory -Force | Out-Null New-Item -ItemType Directory -Path $packageRoot -Force | Out-Null $originalPath = $env:Path $env:Path = "$qtRoot\bin;$mingwBin;$env:Path" try { Push-Location $buildDirectory try { Write-Host 'RUNTIME_EXPORT_STAGE: qmake' & $qmakePath $qtProjectFile 'CONFIG+=release' 'CONFIG-=debug' if ($LASTEXITCODE -ne 0) { throw "qmake 执行失败,退出码:$LASTEXITCODE" } Write-Host 'RUNTIME_EXPORT_STAGE: compile' & $makePath -j2 if ($LASTEXITCODE -ne 0) { throw "mingw32-make 执行失败,退出码:$LASTEXITCODE" } } finally { Pop-Location } if (-not (Test-Path -LiteralPath $executablePath)) { throw "未生成可执行文件:$executablePath" } if (Test-Path -LiteralPath $packageDirectory) { Remove-Item -LiteralPath $packageDirectory -Recurse -Force } if (Test-Path -LiteralPath $archivePath) { Remove-Item -LiteralPath $archivePath -Force } Write-Host 'RUNTIME_EXPORT_STAGE: package' New-Item -ItemType Directory -Path $packageDirectory | Out-Null $packagedExecutable = Join-Path $packageDirectory 'integrated_platform.exe' Copy-Item -LiteralPath $executablePath -Destination $packagedExecutable $runtimeFiles = @( 'Qt5Core.dll', 'Qt5Gui.dll', 'Qt5Network.dll', 'Qt5SerialBus.dll', 'Qt5SerialPort.dll', 'Qt5Widgets.dll', 'libgcc_s_seh-1.dll', 'libstdc++-6.dll', 'libwinpthread-1.dll' ) foreach ($runtimeFile in $runtimeFiles) { $runtimeSource = Join-Path $(if ($runtimeFile -like 'Qt5*') { "$qtRoot\bin" } else { $mingwBin }) $runtimeFile if (-not (Test-Path -LiteralPath $runtimeSource)) { throw "未找到运行库:$runtimeSource" } Copy-Item -LiteralPath $runtimeSource -Destination $packageDirectory } $packagedPlatformDirectory = Join-Path $packageDirectory 'platforms' $packagedStyleDirectory = Join-Path $packageDirectory 'styles' New-Item -ItemType Directory -Path $packagedPlatformDirectory | Out-Null New-Item -ItemType Directory -Path $packagedStyleDirectory | Out-Null Copy-Item -LiteralPath $platformPlugin -Destination $packagedPlatformDirectory Copy-Item -LiteralPath $stylePlugin -Destination $packagedStyleDirectory Write-Host 'RUNTIME_EXPORT_STAGE: verify' foreach ($requiredOutput in @( $packagedExecutable, (Join-Path $packageDirectory 'Qt5Core.dll'), (Join-Path $packageDirectory 'Qt5SerialBus.dll'), (Join-Path $packagedPlatformDirectory 'qwindows.dll') )) { if (-not (Test-Path -LiteralPath $requiredOutput)) { throw "打包结果缺少必要文件:$requiredOutput" } } Compress-Archive -LiteralPath $packageDirectory -DestinationPath $archivePath -CompressionLevel Optimal Write-Host "打包完成" Write-Host "运行目录:$packageDirectory" Write-Host "压缩包:$archivePath" } finally { $env:Path = $originalPath }