Files
bishe-QT/clear_qt_cache.ps1
2026-05-21 08:07:04 +08:00

138 lines
4.3 KiB
PowerShell

#requires -version 5.1
[CmdletBinding(SupportsShouldProcess = $true)]
param(
[string]$ProjectDir,
[switch]$Force
)
Set-StrictMode -Version 2.0
$ErrorActionPreference = 'Stop'
# 函数作用:将传入路径解析为规范化的绝对路径,便于后续安全校验和文件删除操作。
function Resolve-FullPath {
param([Parameter(Mandatory = $true)][string]$Path)
return [IO.Path]::GetFullPath((Resolve-Path -LiteralPath $Path).Path)
}
# 函数作用:确认待删除目标位于指定项目目录内部,避免误删项目外部文件。
function Assert-InsideDirectory {
param(
[Parameter(Mandatory = $true)][string]$Parent,
[Parameter(Mandatory = $true)][string]$Child
)
$parentFull = [IO.Path]::GetFullPath($Parent).TrimEnd([char[]]@('\', '/'))
$childFull = [IO.Path]::GetFullPath($Child).TrimEnd([char[]]@('\', '/'))
$parentPrefix = $parentFull + [IO.Path]::DirectorySeparatorChar
if ($childFull -eq $parentFull -or -not $childFull.StartsWith($parentPrefix, [StringComparison]::OrdinalIgnoreCase)) {
throw "Refusing to remove path outside project: $childFull"
}
}
# 函数作用:检查 Qt Creator、CMake、Ninja 等构建相关进程是否正在运行,防止清理缓存时与构建过程冲突。
function Stop-IfBuildToolsAreRunning {
$names = @('qtcreator', 'cmake', 'ninja', 'jom', 'mingw32-make', 'make')
$running = Get-Process -ErrorAction SilentlyContinue |
Where-Object { $names -contains $_.ProcessName.ToLowerInvariant() } |
Sort-Object ProcessName, Id
if ($running -and -not $Force) {
$summary = ($running | ForEach-Object { "$($_.ProcessName)#$($_.Id)" }) -join ', '
throw "Qt Creator or build tools are running: $summary. Close them first, or rerun with -Force if you are sure."
}
}
# 函数作用:收集当前 Qt 项目下可安全清理的 CMake/Qt Creator 缓存文件和构建目录,并去除重复项。
function Get-CacheTargets {
param([Parameter(Mandatory = $true)][string]$ProjectPath)
$literalNames = @(
'.qtcreator',
'.cmake',
'.qt',
'.qtc_clangd',
'build',
'out',
'CMakeCache.txt',
'CMakeFiles',
'cmake_install.cmake',
'compile_commands.json',
'CTestTestfile.cmake',
'DartConfiguration.tcl',
'install_manifest.txt',
'Makefile',
'CMakeUserPresets.json'
)
$wildcardFilters = @(
'build-*',
'cmake-build-*',
'*.user',
'*.user.*',
'*.autosave'
)
$items = New-Object 'System.Collections.Generic.List[System.IO.FileSystemInfo]'
foreach ($name in $literalNames) {
$path = Join-Path $ProjectPath $name
if (Test-Path -LiteralPath $path) {
$items.Add((Get-Item -LiteralPath $path -Force))
}
}
foreach ($filter in $wildcardFilters) {
Get-ChildItem -LiteralPath $ProjectPath -Force -Filter $filter -ErrorAction SilentlyContinue |
ForEach-Object { $items.Add($_) }
}
$seen = @{}
foreach ($item in $items) {
if (-not $seen.ContainsKey($item.FullName)) {
$seen[$item.FullName] = $true
$item
}
}
}
if ([string]::IsNullOrWhiteSpace($ProjectDir)) {
if (-not [string]::IsNullOrWhiteSpace($PSScriptRoot)) {
$ProjectDir = $PSScriptRoot
} elseif (-not [string]::IsNullOrWhiteSpace($PSCommandPath)) {
$ProjectDir = Split-Path -Parent $PSCommandPath
} else {
$ProjectDir = (Get-Location).Path
}
}
$projectPath = Resolve-FullPath -Path $ProjectDir
if (-not (Test-Path -LiteralPath (Join-Path $projectPath 'CMakeLists.txt'))) {
Write-Warning "CMakeLists.txt was not found in '$projectPath'. Use -ProjectDir to point at the Qt project root."
}
Stop-IfBuildToolsAreRunning
Write-Host "Project: $projectPath"
Write-Host 'Mode: delete current project Qt/CMake cache directly.'
$targets = @(Get-CacheTargets -ProjectPath $projectPath)
if ($targets.Count -eq 0) {
Write-Host 'No cache files found.'
exit 0
}
foreach ($target in $targets) {
Assert-InsideDirectory -Parent $projectPath -Child $target.FullName
if ($PSCmdlet.ShouldProcess($target.FullName, 'Remove Qt/CMake cache')) {
Remove-Item -LiteralPath $target.FullName -Recurse -Force
Write-Host "Removed: $($target.FullName)"
}
}
Write-Host 'Done.'