param( [switch]$Clean, [switch]$SkipGhostscriptBundle, [switch]$SkipDependencyInstall ) $ErrorActionPreference = "Stop" $ProjectRoot = Split-Path -Parent $MyInvocation.MyCommand.Path Set-Location $ProjectRoot $AppName = "ZipBundler" $EntryPoint = Join-Path $ProjectRoot "zipbundler.py" $SplashImage = Join-Path $ProjectRoot "assets\splash.png" if (-not (Test-Path -LiteralPath $EntryPoint)) { throw "File principale non trovato: $EntryPoint" } if (-not (Test-Path -LiteralPath $SplashImage)) { throw "Immagine splash non trovata: $SplashImage" } if ($Clean) { foreach ($relativePath in @("build", "dist", "$AppName.spec")) { $targetPath = [IO.Path]::GetFullPath((Join-Path $ProjectRoot $relativePath)) if (-not $targetPath.StartsWith($ProjectRoot.TrimEnd('\') + '\', [StringComparison]::OrdinalIgnoreCase)) { throw "Percorso di pulizia esterno al progetto: $targetPath" } if (Test-Path -LiteralPath $targetPath) { $targetItem = Get-Item -LiteralPath $targetPath -Force if ($targetItem.Attributes -band [IO.FileAttributes]::ReparsePoint) { throw "Pulizia non consentita su collegamenti: $targetPath" } Remove-Item -LiteralPath $targetPath -Recurse -Force } } } if (-not $SkipDependencyInstall) { python -m pip install -r requirements.txt if ($LASTEXITCODE -ne 0) { throw "Installazione dipendenze non riuscita." } python -m pip install pyinstaller if ($LASTEXITCODE -ne 0) { throw "Installazione PyInstaller non riuscita." } } $argsList = @( "--noconfirm", "--clean", "--windowed", "--onefile", "--name", $AppName, "--splash", $SplashImage, "--add-data", "$SplashImage;assets", "--collect-all", "customtkinter", "--hidden-import", "customtkinter", "--hidden-import", "PIL._tkinter_finder", "--hidden-import", "fitz", "--hidden-import", "win32com", "--hidden-import", "win32com.client", "--hidden-import", "pythoncom", "--hidden-import", "pywintypes" ) if (-not $SkipGhostscriptBundle) { $ghostscriptCommand = Get-Command gswin64c.exe, gswin32c.exe, gs.exe -ErrorAction SilentlyContinue | Select-Object -First 1 if ($ghostscriptCommand) { $ghostscriptBin = Split-Path -Parent $ghostscriptCommand.Source $ghostscriptRoot = Split-Path -Parent $ghostscriptBin Write-Host "Includo Ghostscript da: $ghostscriptRoot" $argsList += @("--add-data", "$ghostscriptRoot;ghostscript") } else { throw "Ghostscript non trovato nel PATH: impossibile creare la build completa." } } else { Write-Warning "Bundle Ghostscript saltato per richiesta esplicita." } $argsList += $EntryPoint python -m PyInstaller @argsList if ($LASTEXITCODE -ne 0) { throw "PyInstaller non ha completato la build." } $exePath = Join-Path $ProjectRoot "dist\$AppName.exe" if (Test-Path -LiteralPath $exePath) { Write-Host "" Write-Host "Build completata:" Write-Host $exePath } else { throw "Build completata senza trovare l'eseguibile atteso: $exePath" }