From 315f3d51630a8eecb7152cdfeeb34e9ad1a4307c Mon Sep 17 00:00:00 2001 From: Patedam Date: Thu, 23 Jul 2026 13:00:01 -0400 Subject: [PATCH] basic incremental build --- misc/build.bat | 278 +++++++++++++++++++--------------------- misc/build_helper.ps1 | 163 +++++++++++++++++++++++ misc/check_target.ps1 | 29 +++++ misc/clean_unity.ps1 | 61 +++++++++ misc/summary_helper.ps1 | 39 ++++++ 5 files changed, 424 insertions(+), 146 deletions(-) create mode 100644 misc/build_helper.ps1 create mode 100644 misc/check_target.ps1 create mode 100644 misc/clean_unity.ps1 create mode 100644 misc/summary_helper.ps1 diff --git a/misc/build.bat b/misc/build.bat index d783a9a..793e956 100644 --- a/misc/build.bat +++ b/misc/build.bat @@ -4,159 +4,93 @@ setlocal enabledelayedexpansion :: ------------------------------------------------------------------------------ :: Unity Build Script (misc/build.bat) :: Step 1: Use FASTBuild to generate unity .cpp files directly in Intermediate/ -:: Step 2: Invoke compiler (clang-cl / cl) directly on target unity files +:: Step 2: Invoke compiler directly on target unity files :: ------------------------------------------------------------------------------ set SCRIPT_DIR=%~dp0 cd /d "%SCRIPT_DIR%.." set FBUILD=misc\fbuild.exe +set HELPER=powershell -NoProfile -ExecutionPolicy Bypass -File "%SCRIPT_DIR%build_helper.ps1" set TARGET_JULIET=0 set TARGET_ROMEO=0 set TARGET_SHADER=0 set TARGET_GAME=0 -set TARGET_COUNT=0 +set TARGET_SPECIFIED=0 set CONFIG_DEBUG=0 set CONFIG_RELEASE=0 set CONFIG_PROFILE=0 -set CONFIG_COUNT=0 +set CONFIG_SPECIFIED=0 :parse_args if "%~1"=="" goto check_defaults - -if /i "%~1"=="debug" ( - set CONFIG_DEBUG=1 - set /a CONFIG_COUNT+=1 - shift - goto parse_args -) - -if /i "%~1"=="release" ( - set CONFIG_RELEASE=1 - set /a CONFIG_COUNT+=1 - shift - goto parse_args -) - -if /i "%~1"=="profile" ( - set CONFIG_PROFILE=1 - set /a CONFIG_COUNT+=1 - shift - goto parse_args -) - -if /i "%~1"=="juliet" ( - set TARGET_JULIET=1 - set /a TARGET_COUNT+=1 - shift - goto parse_args -) - -if /i "%~1"=="game" ( - set TARGET_GAME=1 - set /a TARGET_COUNT+=1 - shift - goto parse_args -) - -if /i "%~1"=="romeo" ( - set TARGET_ROMEO=1 - set /a TARGET_COUNT+=1 - shift - goto parse_args -) - -if /i "%~1"=="shadercompiler" ( - set TARGET_SHADER=1 - set /a TARGET_COUNT+=1 - shift - goto parse_args -) - +if /i "%~1"=="debug" set CONFIG_DEBUG=1& set CONFIG_SPECIFIED=1 +if /i "%~1"=="release" set CONFIG_RELEASE=1& set CONFIG_SPECIFIED=1 +if /i "%~1"=="profile" set CONFIG_PROFILE=1& set CONFIG_SPECIFIED=1 +if /i "%~1"=="juliet" set TARGET_JULIET=1& set TARGET_SPECIFIED=1 +if /i "%~1"=="game" set TARGET_GAME=1& set TARGET_SPECIFIED=1 +if /i "%~1"=="romeo" set TARGET_ROMEO=1& set TARGET_SPECIFIED=1 +if /i "%~1"=="shadercompiler" set TARGET_SHADER=1& set TARGET_SPECIFIED=1 shift goto parse_args :check_defaults -:: If no arguments passed ("build"), build ALL targets across ALL configurations (Debug, Profile, Release) -if !CONFIG_COUNT! equ 0 if !TARGET_COUNT! equ 0 ( - set CONFIG_DEBUG=1 - set CONFIG_RELEASE=1 - set CONFIG_PROFILE=1 - set TARGET_JULIET=1 - set TARGET_GAME=1 - set TARGET_ROMEO=1 - set TARGET_SHADER=1 - goto start_build -) - -:: If targets specified but no configs specified, default to Debug -if !CONFIG_COUNT! equ 0 ( +if !CONFIG_SPECIFIED! equ 0 ( + if !TARGET_SPECIFIED! equ 0 ( + set CONFIG_DEBUG=1& set CONFIG_RELEASE=1& set CONFIG_PROFILE=1 + set TARGET_JULIET=1& set TARGET_GAME=1& set TARGET_ROMEO=1& set TARGET_SHADER=1 + goto start_build + ) set CONFIG_DEBUG=1 ) - -:: If configs specified but no targets specified, build all targets for those configs -if !TARGET_COUNT! equ 0 ( - set TARGET_JULIET=1 - set TARGET_GAME=1 - set TARGET_ROMEO=1 - set TARGET_SHADER=1 +if !TARGET_SPECIFIED! equ 0 ( + set TARGET_JULIET=1& set TARGET_GAME=1& set TARGET_ROMEO=1& set TARGET_SHADER=1 ) :start_build -set START_TIME=%TIME% -powershell -Command "$global:startTime = [System.Diagnostics.Stopwatch]::StartNew(); Set-Variable -Name GLOBAL_START_TIME -Value $global:startTime -Scope Global" >nul 2>&1 +%HELPER% -Action StartBuild >nul 2>&1 +if exist "Intermediate\built_outputs.tmp" del /f /q "Intermediate\built_outputs.tmp" >nul 2>&1 if not exist "%FBUILD%" ( - echo. echo [BUILD FAILED] Could not find %FBUILD%. exit /b 1 ) -:: Find Clang / MSVC compiler set COMPILER=clang-cl.exe where %COMPILER% >nul 2>nul -if %ERRORLEVEL% neq 0 ( +if !ERRORLEVEL! neq 0 ( set COMPILER=cl.exe + where %COMPILER% >nul 2>nul + if !ERRORLEVEL! neq 0 ( + echo [BUILD FAILED] Neither clang-cl.exe nor cl.exe was found in PATH. + exit /b 1 + ) ) -:: Store start timestamp in PowerShell variable for exact timing across batch routines -powershell -Command "[System.IO.File]::WriteAllText('Intermediate\build_start.tmp', [System.DateTime]::Now.Ticks.ToString())" >nul 2>&1 - -:: Clear temporary built output list file -if exist "Intermediate\built_outputs.tmp" del "Intermediate\built_outputs.tmp" - if !CONFIG_DEBUG! equ 1 call :build_config Debug -if %ERRORLEVEL% neq 0 exit /b %ERRORLEVEL% +if !ERRORLEVEL! neq 0 exit /b !ERRORLEVEL! if !CONFIG_PROFILE! equ 1 call :build_config Profile -if %ERRORLEVEL% neq 0 exit /b %ERRORLEVEL% +if !ERRORLEVEL! neq 0 exit /b !ERRORLEVEL! if !CONFIG_RELEASE! equ 1 call :build_config Release -if %ERRORLEVEL% neq 0 exit /b %ERRORLEVEL% - -:: Calculate build elapsed time using PowerShell -for /f "usebackq tokens=*" %%I in (`powershell -Command "$start = [long](Get-Content Intermediate\build_start.tmp); $elapsed = (New-Object System.TimeSpan ([System.DateTime]::Now.Ticks - $start)); Remove-Item Intermediate\build_start.tmp -ErrorAction SilentlyContinue; '{0:D2}:{1:D2}:{2:D2}.{3:D3}' -f $elapsed.Hours, $elapsed.Minutes, $elapsed.Seconds, $elapsed.Milliseconds"` ) do set ELAPSED_TIME=%%I +if !ERRORLEVEL! neq 0 exit /b !ERRORLEVEL! echo. echo ============================================================================== echo [BUILD SUMMARY] echo ============================================================================== echo Compiler Used : %COMPILER% -echo Total Duration : %ELAPSED_TIME% -echo Output Binaries: -if exist "Intermediate\built_outputs.tmp" ( - powershell -Command "Get-Content Intermediate\built_outputs.tmp | Get-Item | ForEach-Object { $size = '{0:N2} MB' -f ($_.Length / 1MB); Write-Host (' - ' + $_.FullName.Replace((Get-Location).Path + '\', '') + ' (' + $size + ')') }" - del "Intermediate\built_outputs.tmp" >nul 2>&1 -) +%HELPER% -Action FinishBuild echo ============================================================================== -echo [ALL BUILDS SUCCEEDED] All requested executables built successfully. +echo [ALL BUILDS SUCCEEDED] All requested targets processed successfully. echo ============================================================================== exit /b 0 :: ------------------------------------------------------------------------------ -:: Subroutine to build a specific configuration (Debug / Profile / Release) +:: Build Configuration Subroutine :: ------------------------------------------------------------------------------ :build_config set "CFG=%~1" @@ -173,17 +107,48 @@ if !TARGET_GAME! equ 1 set FASTBUILD_TARGETS=!FASTBUILD_TARGETS! Game-Unity if !TARGET_ROMEO! equ 1 set FASTBUILD_TARGETS=!FASTBUILD_TARGETS! Romeo-Unity if !TARGET_SHADER! equ 1 set FASTBUILD_TARGETS=!FASTBUILD_TARGETS! JulietShaderCompiler-Unity +%HELPER% -Action StartUnity >nul 2>&1 + "%FBUILD%" !FASTBUILD_TARGETS! -if %ERRORLEVEL% neq 0 ( - echo. - echo ============================================================================== +if !ERRORLEVEL! neq 0 ( echo [BUILD FAILED] FASTBuild failed to generate unity files for %CFG%. - echo ============================================================================== - exit /b %ERRORLEVEL% + exit /b !ERRORLEVEL! ) -:: Strip '#pragma message' from generated Unity files -powershell -Command "Get-ChildItem -Path Intermediate -Recurse -Filter '*_Unity*.cpp' | ForEach-Object { (Get-Content $_.FullName) | Where-Object { $_ -notmatch '#pragma message' } | Set-Content $_.FullName }" +:: Evaluate all target needs in a single fast PowerShell pass +%HELPER% -Action EvaluateConfig -CFG "!CFG!" -TargetJuliet "!TARGET_JULIET!" -TargetGame "!TARGET_GAME!" -TargetRomeo "!TARGET_ROMEO!" -TargetShader "!TARGET_SHADER!" >nul 2>&1 + +set FASTBUILD_UNITY_CHANGED=0 +set JULIET_NEED_COMPILE=0 +set IMGUI_NEED_COMPILE=0 +set GAME_NEED_COMPILE=0 +set JULIETAPP_NEED_COMPILE=0 +set ROMEO_NEED_COMPILE=0 +set SHADER_NEED_COMPILE=0 + +if exist "Intermediate\config_status.tmp" ( + for /f "usebackq tokens=1,2 delims==" %%A in ("Intermediate\config_status.tmp") do set %%A=%%B + del /f /q "Intermediate\config_status.tmp" >nul 2>&1 +) + +if !FASTBUILD_UNITY_CHANGED! equ 1 ( + echo [FASTBuild] Unity structure or source file list changed. +) else ( + echo [FASTBuild] No Unity file structure changes detected [up-to-date]. +) + +set ANY_NEED_BUILD=0 +if !JULIET_NEED_COMPILE! equ 1 set ANY_NEED_BUILD=1 +if !IMGUI_NEED_COMPILE! equ 1 set ANY_NEED_BUILD=1 +if !GAME_NEED_COMPILE! equ 1 set ANY_NEED_BUILD=1 +if !JULIETAPP_NEED_COMPILE! equ 1 set ANY_NEED_BUILD=1 +if !ROMEO_NEED_COMPILE! equ 1 set ANY_NEED_BUILD=1 +if !SHADER_NEED_COMPILE! equ 1 set ANY_NEED_BUILD=1 + +if !ANY_NEED_BUILD! equ 0 ( + echo [SKIP / UP-TO-DATE] All requested targets in [%CFG%] are up-to-date. + exit /b 0 +) echo. echo ============================================================================== @@ -208,79 +173,100 @@ if /i "!CFG!"=="Debug" ( set COMMON_LIBS=kernel32.lib user32.lib gdi32.lib dxguid.lib Ws2_32.lib dxgi.lib imm32.lib dwmapi.lib d3dcompiler.lib shell32.lib winhttp.lib delayimp.lib -:: Compile shared Juliet (and ImGui) Object Files into Intermediate\x64-!CFG!\ +:: --- Juliet Shared Objs --- echo. echo --- Compiling Shared Object Files (Juliet / ImGui) [%CFG%] --- -%COMPILER% %COMPILER_FLAGS% /DJULIET_EXPORT /c Intermediate\Juliet\*.cpp /Fo"Intermediate\x64-!CFG!\\" -if %ERRORLEVEL% neq 0 exit /b %ERRORLEVEL% +if !JULIET_NEED_COMPILE! equ 0 ( + echo [SKIP / UP-TO-DATE] Intermediate\x64-!CFG!\Juliet_Unity*.obj [Unity files unchanged] +) else ( + echo [REBUILDING] Compiling Intermediate\x64-!CFG!\Juliet_Unity*.obj... + %COMPILER% %COMPILER_FLAGS% /DJULIET_EXPORT /c Intermediate\Juliet\*.cpp /Fo"Intermediate\x64-!CFG!\\" + if !ERRORLEVEL! neq 0 exit /b !ERRORLEVEL! +) +:: --- ImGui Shared Objs --- if defined IMGUI_UNITY_SRCS ( - %COMPILER% %COMPILER_FLAGS% /c !IMGUI_UNITY_SRCS! /Fo"Intermediate\x64-!CFG!\\" - if %ERRORLEVEL% neq 0 exit /b %ERRORLEVEL% + if !IMGUI_NEED_COMPILE! equ 0 ( + echo [SKIP / UP-TO-DATE] Intermediate\x64-!CFG!\ImGui_Unity*.obj [Unity files unchanged] + ) else ( + echo [REBUILDING] Compiling Intermediate\x64-!CFG!\ImGui_Unity*.obj... + %COMPILER% %COMPILER_FLAGS% /c !IMGUI_UNITY_SRCS! /Fo"Intermediate\x64-!CFG!\\" + if !ERRORLEVEL! neq 0 exit /b !ERRORLEVEL! + ) ) set JULIET_OBJS=Intermediate\x64-!CFG!\Juliet_Unity*.obj set IMGUI_OBJS= -if defined IMGUI_UNITY_SRCS ( - set IMGUI_OBJS=Intermediate\x64-!CFG!\ImGui_Unity*.obj -) +if defined IMGUI_UNITY_SRCS set IMGUI_OBJS=Intermediate\x64-!CFG!\ImGui_Unity*.obj set BUILD_GAME_DLL=0 if !TARGET_JULIET! equ 1 set BUILD_GAME_DLL=1 if !TARGET_GAME! equ 1 set BUILD_GAME_DLL=1 -:: Compile Game.dll +:: --- Game.dll --- if !BUILD_GAME_DLL! equ 1 ( echo. echo --- Building Game.dll [%CFG%] --- - %COMPILER% %COMPILER_FLAGS% /DJULIET_EXPORT /LD /Fe"bin\x64-!CFG!\Game.dll" ^ - %JULIET_OBJS% ^ - Intermediate\Game\*.cpp ^ - %IMGUI_OBJS% ^ - /link %COMMON_LIBS% /INCREMENTAL /ILK:"Intermediate\x64-!CFG!\Game.ilk" /PDB:"Intermediate\x64-!CFG!\Game.pdb" - if %ERRORLEVEL% neq 0 exit /b %ERRORLEVEL% - echo bin\x64-!CFG!\Game.dll>>Intermediate\built_outputs.tmp + if !GAME_NEED_COMPILE! equ 0 ( + echo [SKIP / UP-TO-DATE] bin\x64-!CFG!\Game.dll [Binary up to date, skipping compilation] + ) else ( + echo [REBUILDING] Compiling bin\x64-!CFG!\Game.dll... + %COMPILER% %COMPILER_FLAGS% /DJULIET_EXPORT /LD /Fe"bin\x64-!CFG!\Game.dll" ^ + %JULIET_OBJS% Intermediate\Game\*.cpp %IMGUI_OBJS% ^ + /link %COMMON_LIBS% /INCREMENTAL /ILK:"Intermediate\x64-!CFG!\Game.ilk" /PDB:"Intermediate\x64-!CFG!\Game.pdb" + if !ERRORLEVEL! neq 0 exit /b !ERRORLEVEL! + echo bin\x64-!CFG!\Game.dll>>Intermediate\built_outputs.tmp + ) ) -:: Compile JulietApp Executable +:: --- JulietApp.exe --- if !TARGET_JULIET! equ 1 ( echo. echo --- Building JulietApp.exe [%CFG%] --- - %COMPILER% %COMPILER_FLAGS% /Fe"bin\x64-!CFG!\JulietApp.exe" ^ - Intermediate\JulietApp\*.cpp ^ - %IMGUI_OBJS% ^ - /link %COMMON_LIBS% bin\x64-!CFG!\Game.lib /SUBSYSTEM:CONSOLE /INCREMENTAL /ILK:"Intermediate\x64-!CFG!\JulietApp.ilk" /PDB:"Intermediate\x64-!CFG!\JulietApp.pdb" - if %ERRORLEVEL% neq 0 exit /b %ERRORLEVEL% - echo bin\x64-!CFG!\JulietApp.exe>>Intermediate\built_outputs.tmp + if !JULIETAPP_NEED_COMPILE! equ 0 ( + echo [SKIP / UP-TO-DATE] bin\x64-!CFG!\JulietApp.exe [Binary up to date, skipping compilation] + ) else ( + echo [REBUILDING] Compiling bin\x64-!CFG!\JulietApp.exe... + %COMPILER% %COMPILER_FLAGS% /Fe"bin\x64-!CFG!\JulietApp.exe" ^ + Intermediate\JulietApp\*.cpp %IMGUI_OBJS% ^ + /link %COMMON_LIBS% bin\x64-!CFG!\Game.lib /SUBSYSTEM:CONSOLE /INCREMENTAL /ILK:"Intermediate\x64-!CFG!\JulietApp.ilk" /PDB:"Intermediate\x64-!CFG!\JulietApp.pdb" + if !ERRORLEVEL! neq 0 exit /b !ERRORLEVEL! + echo bin\x64-!CFG!\JulietApp.exe>>Intermediate\built_outputs.tmp + ) ) -:: Compile Romeo Executable +:: --- Romeo.exe --- if !TARGET_ROMEO! equ 1 ( echo. echo --- Building Romeo.exe [%CFG%] --- - %COMPILER% %COMPILER_FLAGS% /Fe"bin\x64-!CFG!\Romeo.exe" ^ - %JULIET_OBJS% ^ - Intermediate\Romeo\*.cpp ^ - %IMGUI_OBJS% ^ - /link %COMMON_LIBS% /SUBSYSTEM:CONSOLE /INCREMENTAL /ILK:"Intermediate\x64-!CFG!\Romeo.ilk" /PDB:"Intermediate\x64-!CFG!\Romeo.pdb" - if %ERRORLEVEL% neq 0 exit /b %ERRORLEVEL% - echo bin\x64-!CFG!\Romeo.exe>>Intermediate\built_outputs.tmp + if !ROMEO_NEED_COMPILE! equ 0 ( + echo [SKIP / UP-TO-DATE] bin\x64-!CFG!\Romeo.exe [Binary up to date, skipping compilation] + ) else ( + echo [REBUILDING] Compiling bin\x64-!CFG!\Romeo.exe... + %COMPILER% %COMPILER_FLAGS% /Fe"bin\x64-!CFG!\Romeo.exe" ^ + %JULIET_OBJS% Intermediate\Romeo\*.cpp %IMGUI_OBJS% ^ + /link %COMMON_LIBS% /SUBSYSTEM:CONSOLE /INCREMENTAL /ILK:"Intermediate\x64-!CFG!\Romeo.ilk" /PDB:"Intermediate\x64-!CFG!\Romeo.pdb" + if !ERRORLEVEL! neq 0 exit /b !ERRORLEVEL! + echo bin\x64-!CFG!\Romeo.exe>>Intermediate\built_outputs.tmp + ) ) -:: Compile JulietShaderCompiler Executable +:: --- JulietShaderCompiler.exe --- if !TARGET_SHADER! equ 1 ( echo. echo --- Building JulietShaderCompiler.exe [%CFG%] --- if exist "Intermediate\JulietShaderCompiler\*.cpp" ( - %COMPILER% %COMPILER_FLAGS% /I"JulietShaderCompiler" /Fe"bin\x64-!CFG!\JulietShaderCompiler.exe" ^ - %JULIET_OBJS% ^ - Intermediate\JulietShaderCompiler\*.cpp ^ - %IMGUI_OBJS% ^ - /link %COMMON_LIBS% dxcompiler.lib /DELAYLOAD:dxcompiler.dll /SUBSYSTEM:CONSOLE /INCREMENTAL /ILK:"Intermediate\x64-!CFG!\JulietShaderCompiler.ilk" /PDB:"Intermediate\x64-!CFG!\JulietShaderCompiler.pdb" - if %ERRORLEVEL% neq 0 exit /b %ERRORLEVEL% - echo bin\x64-!CFG!\JulietShaderCompiler.exe>>Intermediate\built_outputs.tmp + if !SHADER_NEED_COMPILE! equ 0 ( + echo [SKIP / UP-TO-DATE] bin\x64-!CFG!\JulietShaderCompiler.exe [Binary up to date, skipping compilation] + ) else ( + echo [REBUILDING] Compiling bin\x64-!CFG!\JulietShaderCompiler.exe... + %COMPILER% %COMPILER_FLAGS% /I"JulietShaderCompiler" /Fe"bin\x64-!CFG!\JulietShaderCompiler.exe" ^ + %JULIET_OBJS% Intermediate\JulietShaderCompiler\*.cpp %IMGUI_OBJS% ^ + /link %COMMON_LIBS% dxcompiler.lib /DELAYLOAD:dxcompiler.dll /SUBSYSTEM:CONSOLE /INCREMENTAL /ILK:"Intermediate\x64-!CFG!\JulietShaderCompiler.ilk" /PDB:"Intermediate\x64-!CFG!\JulietShaderCompiler.pdb" + if !ERRORLEVEL! neq 0 exit /b !ERRORLEVEL! + echo bin\x64-!CFG!\JulietShaderCompiler.exe>>Intermediate\built_outputs.tmp + ) ) ) exit /b 0 - diff --git a/misc/build_helper.ps1 b/misc/build_helper.ps1 new file mode 100644 index 0000000..3fba66a --- /dev/null +++ b/misc/build_helper.ps1 @@ -0,0 +1,163 @@ +# 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" + } +} diff --git a/misc/check_target.ps1 b/misc/check_target.ps1 new file mode 100644 index 0000000..51c394f --- /dev/null +++ b/misc/check_target.ps1 @@ -0,0 +1,29 @@ +# check_target.ps1 - Checks if target binary needs to be rebuilt based on binary existence and source file modification times +param( + [string]$TargetBinary, + [string]$SearchDirs +) + +if (-not (Test-Path $TargetBinary)) { + Set-Content -Path "Intermediate\need_build.tmp" -Value "1" + exit 0 +} + +$binTime = (Get-Item $TargetBinary).LastWriteTime +$dirs = $SearchDirs -split ',' + +$needsRebuild = "0" +foreach ($dir in $dirs) { + if (Test-Path $dir) { + # Check source .cpp, .h, .hpp, .inl files for changes newer than target binary + $newer = Get-ChildItem -Path $dir -Recurse -File -ErrorAction SilentlyContinue | Where-Object { + ($_.Extension -eq '.cpp' -or $_.Extension -eq '.h' -or $_.Extension -eq '.hpp' -or $_.Extension -eq '.inl') -and $_.LastWriteTime -gt $binTime + } + if ($newer) { + $needsRebuild = "1" + break + } + } +} + +Set-Content -Path "Intermediate\need_build.tmp" -Value $needsRebuild diff --git a/misc/clean_unity.ps1 b/misc/clean_unity.ps1 new file mode 100644 index 0000000..f9490be --- /dev/null +++ b/misc/clean_unity.ps1 @@ -0,0 +1,61 @@ +# clean_unity.ps1 - Manages Unity files content hashing and change detection +param( + [string]$Action = "Finish" +) + +if (-not (Test-Path "Intermediate")) { New-Item -ItemType Directory -Path "Intermediate" | Out-Null } + +$hashFile = "Intermediate\unity_hashes.tmp" + +if ($Action -eq "Start") { + # 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 $hashFile -ErrorAction SilentlyContinue +} +elseif ($Action -eq "Finish") { + $oldHashes = @{} + if (Test-Path $hashFile) { + try { + $json = Get-Content $hashFile -Raw -ErrorAction SilentlyContinue + if ($json) { + $obj = $json | ConvertFrom-Json + foreach ($prop in $obj.PSObject.Properties) { + $oldHashes[$prop.Name] = $prop.Value + } + } + } catch {} + Remove-Item $hashFile -ErrorAction SilentlyContinue + } + + # Clean '#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) + } + } + + # Detect if any Unity file is new or has changed content + $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 + } + } + } + + Set-Content -Path "Intermediate\unity_changed.tmp" -Value $unityChanged +} diff --git a/misc/summary_helper.ps1 b/misc/summary_helper.ps1 new file mode 100644 index 0000000..459b7da --- /dev/null +++ b/misc/summary_helper.ps1 @@ -0,0 +1,39 @@ +# summary_helper.ps1 - Handles build timing and summary reporting cleanly +param( + [string]$Action +) + +if ($Action -eq "Start") { + if (-not (Test-Path "Intermediate")) { New-Item -ItemType Directory -Path "Intermediate" | Out-Null } + [System.IO.File]::WriteAllText("Intermediate\build_start.tmp", [System.DateTime]::Now.Ticks.ToString()) +} +elseif ($Action -eq "Finish") { + $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)" + } +}