# misc/build_helper.ps1 - Unified Build Utility Script param( [string]$Action, [string]$CFG, [string]$TargetJuliet = "0", [string]$TargetGame = "0", [string]$TargetRomeo = "0", [string]$TargetShader = "0" ) if (-not (Test-Path "Intermediate")) { New-Item -ItemType Directory -Path "Intermediate" | Out-Null } switch ($Action) { "StartBuild" { [System.IO.File]::WriteAllText("Intermediate\build_start.tmp", [System.DateTime]::Now.Ticks.ToString()) } "FinishBuild" { $elapsedStr = "00:00:00.000" if (Test-Path "Intermediate\build_start.tmp") { $startStr = Get-Content "Intermediate\build_start.tmp" -ErrorAction SilentlyContinue if ($startStr) { $startTicks = [long]$startStr $elapsed = New-Object System.TimeSpan ([System.DateTime]::Now.Ticks - $startTicks) $elapsedStr = "{0:D2}:{1:D2}:{2:D2}.{3:D3}" -f $elapsed.Hours, $elapsed.Minutes, $elapsed.Seconds, $elapsed.Milliseconds } Remove-Item "Intermediate\build_start.tmp" -ErrorAction SilentlyContinue } Write-Host "Total Duration : $elapsedStr" Write-Host "Output Binaries:" if (Test-Path "Intermediate\built_outputs.tmp") { $files = Get-Content "Intermediate\built_outputs.tmp" -ErrorAction SilentlyContinue | Where-Object { Test-Path $_ } if ($files) { foreach ($f in $files) { $item = Get-Item $f $size = "{0:N2} MB" -f ($item.Length / 1MB) $relPath = $item.FullName.Replace((Get-Location).Path + "\", "") Write-Host " - $relPath ($size)" } } else { Write-Host " - None built in this session (all requested targets up-to-date)" } Remove-Item "Intermediate\built_outputs.tmp" -ErrorAction SilentlyContinue } else { Write-Host " - None built in this session (all requested targets up-to-date)" } } "StartUnity" { # Compute SHA256 hashes of all existing Unity files before FASTBuild runs $hashes = @{} Get-ChildItem -Path "Intermediate" -Recurse -Filter "*_Unity*.cpp" -ErrorAction SilentlyContinue | ForEach-Object { $hash = (Get-FileHash -Path $_.FullName -Algorithm SHA256).Hash $hashes[$_.FullName] = $hash } $hashes | ConvertTo-Json | Set-Content -Path "Intermediate\unity_hashes.tmp" -ErrorAction SilentlyContinue } "EvaluateConfig" { # 1. Strip '#pragma message' from generated Unity files if present Get-ChildItem -Path "Intermediate" -Recurse -Filter "*_Unity*.cpp" -ErrorAction SilentlyContinue | ForEach-Object { $filePath = $_.FullName $lines = [System.IO.File]::ReadAllLines($filePath) $filtered = $lines | Where-Object { $_ -notlike '*#pragma message*' } if ($lines.Count -ne $filtered.Count) { [System.IO.File]::WriteAllLines($filePath, $filtered) } } # 2. Compare Unity hashes to detect Unity structure changes $oldHashes = @{} if (Test-Path "Intermediate\unity_hashes.tmp") { try { $json = Get-Content "Intermediate\unity_hashes.tmp" -Raw -ErrorAction SilentlyContinue if ($json) { $obj = $json | ConvertFrom-Json foreach ($prop in $obj.PSObject.Properties) { $oldHashes[$prop.Name] = $prop.Value } } } catch {} Remove-Item "Intermediate\unity_hashes.tmp" -ErrorAction SilentlyContinue } $unityChanged = "0" $currentFiles = Get-ChildItem -Path "Intermediate" -Recurse -Filter "*_Unity*.cpp" -ErrorAction SilentlyContinue if (-not $currentFiles) { $unityChanged = "1" } else { foreach ($file in $currentFiles) { $path = $file.FullName $newHash = (Get-FileHash -Path $path -Algorithm SHA256).Hash if (-not $oldHashes.ContainsKey($path) -or $oldHashes[$path] -ne $newHash) { $unityChanged = "1" break } } } # Helper function to check if target binary/obj is missing or older than source files in dirs function Test-NeedRebuild([string]$targetFile, [string[]]$dirs) { if (-not (Test-Path $targetFile)) { return "1" } if ($unityChanged -eq "1") { return "1" } $targetTime = (Get-Item $targetFile).LastWriteTime foreach ($d in $dirs) { if (Test-Path $d) { $newer = Get-ChildItem -Path $d -Recurse -File -ErrorAction SilentlyContinue | Where-Object { ($_.Extension -eq '.cpp' -or $_.Extension -eq '.h' -or $_.Extension -eq '.hpp' -or $_.Extension -eq '.inl') -and $_.LastWriteTime -gt $targetTime } if ($newer) { return "1" } } } return "0" } $julietObj = "Intermediate\x64-$CFG\Juliet_Unity1.obj" $imguiObj = "Intermediate\x64-$CFG\ImGui_Unity1.obj" $gameDll = "bin\x64-$CFG\Game.dll" $julietApp = "bin\x64-$CFG\JulietApp.exe" $romeoExe = "bin\x64-$CFG\Romeo.exe" $shaderExe = "bin\x64-$CFG\JulietShaderCompiler.exe" $julietNeed = Test-NeedRebuild $julietObj @("Juliet") $imguiNeed = Test-NeedRebuild $imguiObj @("External/imgui") $gameNeed = "0" if ($TargetJuliet -eq "1" -or $TargetGame -eq "1") { $gameNeed = Test-NeedRebuild $gameDll @("Juliet", "Game", "External/imgui") if ($julietNeed -eq "1") { $gameNeed = "1" } } $julietAppNeed = "0" if ($TargetJuliet -eq "1") { $julietAppNeed = Test-NeedRebuild $julietApp @("JulietApp", "Game", "Juliet", "External/imgui") if ($gameNeed -eq "1") { $julietAppNeed = "1" } } $romeoNeed = "0" if ($TargetRomeo -eq "1") { $romeoNeed = Test-NeedRebuild $romeoExe @("Romeo", "Juliet", "External/imgui") if ($julietNeed -eq "1") { $romeoNeed = "1" } } $shaderNeed = "0" if ($TargetShader -eq "1" -and (Test-Path "Intermediate\JulietShaderCompiler\*.cpp")) { $shaderNeed = Test-NeedRebuild $shaderExe @("JulietShaderCompiler", "Juliet", "External/imgui") if ($julietNeed -eq "1") { $shaderNeed = "1" } } $lines = @( "FASTBUILD_UNITY_CHANGED=$unityChanged", "JULIET_NEED_COMPILE=$julietNeed", "IMGUI_NEED_COMPILE=$imguiNeed", "GAME_NEED_COMPILE=$gameNeed", "JULIETAPP_NEED_COMPILE=$julietAppNeed", "ROMEO_NEED_COMPILE=$romeoNeed", "SHADER_NEED_COMPILE=$shaderNeed" ) $lines | Set-Content -Path "Intermediate\config_status.tmp" } }