From c1163e39e43adf3c707c4f5b8e2e7b6802ba2fa9 Mon Sep 17 00:00:00 2001 From: omigamedev Date: Wed, 17 Jun 2026 09:36:21 +0200 Subject: [PATCH] Quiet platform and Apple validation wrappers --- CMakeLists.txt | 6 ++ docs/modernization/build-inventory.md | 3 + docs/modernization/roadmap.md | 24 +++++ docs/modernization/tasks.md | 28 +++++ scripts/automation/apple-remote-build.ps1 | 82 ++++++++++++++- scripts/automation/platform-build.ps1 | 121 ++++++++++++++++++++-- scripts/automation/quiet-validate.ps1 | 91 +++++++++++++++- 7 files changed, 343 insertions(+), 12 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 326764c5..1140903e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -254,6 +254,12 @@ target_link_libraries(pp_platform_api add_library(pp_platform_apple STATIC ${PP_PLATFORM_APPLE_SOURCES}) +if(APPLE) + set_source_files_properties( + src/platform_apple/apple_platform_state.cpp + PROPERTIES + LANGUAGE OBJCXX) +endif() target_include_directories(pp_platform_apple PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/src") diff --git a/docs/modernization/build-inventory.md b/docs/modernization/build-inventory.md index 41ca4743..c099f8fd 100644 --- a/docs/modernization/build-inventory.md +++ b/docs/modernization/build-inventory.md @@ -66,6 +66,7 @@ keeps known warning/noise filters in ```powershell powershell -ExecutionPolicy Bypass -File scripts\automation\quiet-validate.ps1 -BuildTargets PanoPainter,pano_cli -TestRegex "pp_app_core|pano_cli_plan" powershell -ExecutionPolicy Bypass -File scripts\automation\quiet-validate.ps1 -BuildTargets pp_app_core_app_dialog_tests,pp_ui_core_overlay_lifetime_tests -TestRegex "pp_(app_core_app_dialog|ui_core_(node_lifetime|overlay_lifetime))" +powershell -ExecutionPolicy Bypass -File scripts\automation\quiet-validate.ps1 -BuildTargets ALL_BUILD -IncludePlatformBuild -IncludeAppleRemote ``` ```powershell @@ -85,6 +86,7 @@ ctest --preset desktop-fast-vcpkg --build-config Debug cmake --build --preset windows-msvc-default --config Debug --target panopainter_platform_build_vcpkg_ui_core cmake --preset android-arm64 powershell -ExecutionPolicy Bypass -File scripts\automation\platform-build.ps1 -Presets android-arm64 +powershell -ExecutionPolicy Bypass -File scripts\automation\platform-build.ps1 -Quiet -Presets android-arm64 powershell -ExecutionPolicy Bypass -File scripts\automation\android-legacy-package-build.ps1 -Packages standard powershell -ExecutionPolicy Bypass -File scripts\automation\android-legacy-package-build.ps1 -Packages quest,focus -ConfigureOnly powershell -ExecutionPolicy Bypass -File scripts\automation\package-smoke.ps1 -Preset windows-msvc-default -Configuration Debug @@ -104,6 +106,7 @@ python scripts/dev/clangd_nav.py self-test python scripts/dev/check_platform_build_targets.py python scripts/dev/check_package_smoke_readiness.py powershell -ExecutionPolicy Bypass -File scripts\automation\apple-remote-build.ps1 -Presets macos,ios-simulator,ios-device +powershell -ExecutionPolicy Bypass -File scripts\automation\apple-remote-build.ps1 -Quiet -Presets macos,ios-simulator,ios-device ``` Known local toolchain state: diff --git a/docs/modernization/roadmap.md b/docs/modernization/roadmap.md index 5f03371c..255bfa6e 100644 --- a/docs/modernization/roadmap.md +++ b/docs/modernization/roadmap.md @@ -69,6 +69,16 @@ What is already real: - `pp_platform_api` - `pp_app_core` +Latest slice: +- `scripts/automation/platform-build.ps1` now supports a quiet mode that writes + per-preset configure/build logs and emits only a compact JSON summary. +- `scripts/automation/apple-remote-build.ps1` now supports a quiet mode that + writes the SSH session to a local log, preserves the remote platform-build + log path, and emits only a compact JSON summary. +- `scripts/automation/quiet-validate.ps1` can now bundle quiet platform and + Apple remote validation into the same summary artifact through + `-IncludePlatformBuild` and `-IncludeAppleRemote`. + What is still carrying too much live ownership: - `pp_panopainter_ui`: 34 files, about 9102 lines @@ -92,6 +102,20 @@ Current hotspot files: Latest slice: +- The remaining Windows entry/exit singleton write no longer lives at the + `run_main_application(...)` and `handle_window_close_message(...)` callsites; + `src/platform_windows/windows_runtime_shell.cpp` now centralizes that legacy + `App::I` side effect inside `bind_app(...)`, leaving the touched runtime and + lifecycle shell as explicit binder users instead of direct singleton writers. +- The touched `src/platform_windows/windows_platform_services.cpp` fan-out no + longer reaches the broader retained window bundle directly for main-window, + sandbox, and VR/session reads; the touched window/VR queries now route + through narrow runtime-shell accessors instead. +- `src/platform_windows/windows_bootstrap_helpers.cpp` no longer uses + `Canvas::I` for crash-recovery saves; the BugTrap pre-error handler now uses + the app-owned `NodeCanvas` document (`app.canvas->m_canvas`) and the new + runtime-shell window/sandbox accessors instead of direct singleton or + retained-state reads in the touched recovery path. - The retained Apple document bridge/state pocket no longer lives in `src/platform_legacy/legacy_platform_state.*`; it now lives in the Apple-owned `src/platform_apple/apple_platform_state.cpp` plus diff --git a/docs/modernization/tasks.md b/docs/modernization/tasks.md index cd225415..00ff0bd8 100644 --- a/docs/modernization/tasks.md +++ b/docs/modernization/tasks.md @@ -63,6 +63,9 @@ Completed, blocked, and superseded task history moved to - the Win32 input path now binds the active `WacomTablet*` explicitly through `windows_runtime_shell`, but that tablet binding still lives at a composition edge instead of a broader runtime/platform-owned controller + - the touched Win32 app/window/session queries now route through narrow + runtime-shell accessors, but the broader runtime/thread host still owns + composition-edge global state and shutdown sequencing - thread-affinity rules are enforced by convention and asserts instead of explicit runtime contracts - The UI ownership boundary is not finished: @@ -74,6 +77,17 @@ Completed, blocked, and superseded task history moved to The live app still mostly runs through the same shell and hotspot files, so the queue is now ordered by code movement instead. +Current slice: +- `scripts/automation/platform-build.ps1` now supports `-Quiet`, per-preset log + capture, and compact JSON-only output so Android/headless platform sweeps no + longer flood the console during checkpoint validation. +- `scripts/automation/apple-remote-build.ps1` now supports `-Quiet`, local log + capture for the SSH session, remote log path reporting, and JSON-only output + so Apple remote compile gates no longer stream large tails by default. +- `scripts/automation/quiet-validate.ps1` now accepts + `-IncludePlatformBuild` and `-IncludeAppleRemote` so the existing quiet + wrapper can own the full Windows, Android/platform, and Apple summary path. + ## Active Bundles ### Priority Order @@ -1209,6 +1223,20 @@ Why now: platform-handle state on `App`, which blocks a real `pp_platform_*` shell split. Current slice: +- The remaining Windows entry/exit singleton write no longer lives at the + `run_main_application(...)` and `handle_window_close_message(...)` callsites; + `src/platform_windows/windows_runtime_shell.cpp` now centralizes that legacy + `App::I` side effect inside `bind_app(...)`, leaving the touched runtime and + lifecycle shell as explicit binder users instead of direct singleton writers. +- The touched `src/platform_windows/windows_platform_services.cpp` fan-out no + longer reaches the broader retained window bundle directly for main-window, + sandbox, and VR/session reads; the touched window/VR queries now route + through narrow runtime-shell accessors instead. +- `src/platform_windows/windows_bootstrap_helpers.cpp` no longer uses + `Canvas::I` for crash-recovery saves; the BugTrap pre-error handler now uses + the app-owned `NodeCanvas` document (`app.canvas->m_canvas`) and the new + runtime-shell window/sandbox accessors instead of direct singleton or + retained-state reads in the touched recovery path. - The retained Apple document bridge/state pocket no longer lives in `src/platform_legacy/legacy_platform_state.*`; it now lives in the Apple-owned `src/platform_apple/apple_platform_state.cpp` and diff --git a/scripts/automation/apple-remote-build.ps1 b/scripts/automation/apple-remote-build.ps1 index 9f17e7de..82379a5c 100644 --- a/scripts/automation/apple-remote-build.ps1 +++ b/scripts/automation/apple-remote-build.ps1 @@ -4,7 +4,10 @@ param( [string]$RemoteDirectory = "~/Dev/panopainter", [string]$RepositoryUrl = "ssh://git@git.omar.synology.me:3022/omar/panopainter.git", [string]$Branch = "codex/modernization-cmake-foundation", - [string[]]$Presets = @("macos", "ios-simulator", "ios-device") + [string[]]$Presets = @("macos", "ios-simulator", "ios-device"), + [switch]$Quiet, + [string]$LogDir = "out/logs/apple-remote-build", + [int]$FailureTailLines = 0 ) $ErrorActionPreference = "Stop" @@ -36,6 +39,8 @@ $repositoryLiteral = ConvertTo-ShellSingleQuoted -Value $RepositoryUrl $branchLiteral = ConvertTo-ShellSingleQuoted -Value $Branch $presetLiteral = ConvertTo-ShellSingleQuoted -Value $presetArgument +$quietLiteral = if ($Quiet) { "1" } else { "0" } + $remoteScript = @" set -eu export PATH="/opt/homebrew/bin:/usr/local/bin:`$HOME/tools/bin:`$PATH" @@ -45,6 +50,7 @@ remote_dir=$remoteDirectoryLiteral repository_url=$repositoryLiteral branch_name=$branchLiteral presets=$presetLiteral +quiet_mode=$quietLiteral case "`$remote_dir" in "~/"*) remote_dir="`$HOME/`$(printf '%s' "`$remote_dir" | sed 's|^~/||')" ;; @@ -83,11 +89,79 @@ set -e printf '{"command":"apple-remote-build","host":"%s","branch":"%s","presets":"%s","log":"%s","exitCode":%s}\n' \ "`$(hostname)" "`$branch_name" "`$presets" "`$log" "`$exit_code" -tail -n 80 "`$log" +if [ "`$quiet_mode" != "1" ]; then + tail -n 80 "`$log" +fi exit "`$exit_code" "@ $remoteScript = $remoteScript -replace "`r`n", "`n" $encodedRemoteScript = [Convert]::ToBase64String([System.Text.Encoding]::UTF8.GetBytes($remoteScript)) -& ssh -o BatchMode=yes $HostName "printf '%s' '$encodedRemoteScript' | base64 -D | sh" -exit $LASTEXITCODE +if (-not $Quiet) { + & ssh -o BatchMode=yes $HostName "printf '%s' '$encodedRemoteScript' | base64 -D | sh" + exit $LASTEXITCODE +} + +New-Item -ItemType Directory -Force -Path $LogDir | Out-Null +$runId = Get-Date -Format "yyyyMMdd-HHmmss" +$logPath = Join-Path -Path $LogDir -ChildPath "$runId-apple-remote-build.log" +$stderrPath = Join-Path -Path $LogDir -ChildPath "$runId-apple-remote-build.stderr.log" +$started = Get-Date +$exitCode = 0 +try { + $process = Start-Process ` + -FilePath "ssh" ` + -ArgumentList @("-o", "BatchMode=yes", $HostName, "printf '%s' '$encodedRemoteScript' | base64 -D | sh") ` + -NoNewWindow ` + -Wait ` + -PassThru ` + -RedirectStandardOutput $logPath ` + -RedirectStandardError $stderrPath + $exitCode = $process.ExitCode +} +catch { + $_ | Out-File -LiteralPath $LogPath -Append -Encoding utf8 + $exitCode = 1 +} +finally { + if (Test-Path -LiteralPath $stderrPath) { + Get-Content -LiteralPath $stderrPath | Out-File -LiteralPath $logPath -Append -Encoding utf8 + Remove-Item -LiteralPath $stderrPath -Force + } +} + +$rawLines = if (Test-Path -LiteralPath $logPath) { + @(Get-Content -LiteralPath $logPath) +} else { + @() +} +$remoteSummary = $null +foreach ($line in $rawLines) { + if ($line -match '"command":"apple-remote-build"') { + try { + $remoteSummary = $line | ConvertFrom-Json + } + catch { + } + } +} + +$payload = [ordered]@{ + command = "apple-remote-build" + exitCode = $exitCode + elapsedMs = [int]((Get-Date) - $started).TotalMilliseconds + host = $HostName + branch = $Branch + presets = $Presets + log = $logPath +} +if ($null -ne $remoteSummary) { + $payload.remoteHost = $remoteSummary.host + $payload.remoteLog = $remoteSummary.log +} +if ($exitCode -ne 0 -and $FailureTailLines -gt 0 -and $rawLines.Count -gt 0) { + $payload.failureTail = @($rawLines | Select-Object -Last $FailureTailLines | ForEach-Object { [string]$_ }) +} + +$payload | ConvertTo-Json -Compress -Depth 6 +exit $exitCode diff --git a/scripts/automation/platform-build.ps1 b/scripts/automation/platform-build.ps1 index addda722..9af3825f 100644 --- a/scripts/automation/platform-build.ps1 +++ b/scripts/automation/platform-build.ps1 @@ -80,7 +80,10 @@ param( "pp_app_core_main_toolbar_tests", "pp_app_core_quick_ui_tests", "pp_app_core_tools_menu_tests" - ) + ), + [switch]$Quiet, + [string]$LogDir = "out/logs/platform-build", + [int]$FailureTailLines = 0 ) $ErrorActionPreference = "Stop" @@ -100,6 +103,64 @@ function Expand-ArgumentList { return $expanded } +function Limit-LogSlug { + param( + [string]$Value, + [int]$MaxLength = 96 + ) + + if ($Value.Length -le $MaxLength) { + return $Value + } + return $Value.Substring(0, $MaxLength) +} + +function Invoke-LoggedCommand { + param( + [string]$Command, + [string[]]$Arguments, + [string]$LogPath, + [int]$FailureTailLines + ) + + $started = Get-Date + $exitCode = 0 + $restoreNativeCommandPreference = $false + if (Get-Variable -Name PSNativeCommandUseErrorActionPreference -ErrorAction SilentlyContinue) { + $previousNativeCommandPreference = $PSNativeCommandUseErrorActionPreference + $PSNativeCommandUseErrorActionPreference = $false + $restoreNativeCommandPreference = $true + } + try { + & $Command @Arguments *> $LogPath + $exitCode = $LASTEXITCODE + if ($null -eq $exitCode) { + $exitCode = 0 + } + } + catch { + $_ | Out-File -LiteralPath $LogPath -Append -Encoding utf8 + $exitCode = 1 + } + finally { + if ($restoreNativeCommandPreference) { + $PSNativeCommandUseErrorActionPreference = $previousNativeCommandPreference + } + } + + $result = [ordered]@{ + exitCode = $exitCode + elapsedMs = [int]((Get-Date) - $started).TotalMilliseconds + log = $LogPath + } + + if ($exitCode -ne 0 -and $FailureTailLines -gt 0 -and (Test-Path -LiteralPath $LogPath)) { + $result.failureTail = @(Get-Content -LiteralPath $LogPath -Tail $FailureTailLines | ForEach-Object { [string]$_ }) + } + + return $result +} + function Get-VcpkgRoot { $candidates = @() if ($env:VCPKG_ROOT) { @@ -153,6 +214,11 @@ if ($Presets | Where-Object { $_ -like "android-*" }) { $started = Get-Date $results = @() $overallExitCode = 0 +$runId = Get-Date -Format "yyyyMMdd-HHmmss" + +if ($Quiet) { + New-Item -ItemType Directory -Force -Path $LogDir | Out-Null +} foreach ($preset in $Presets) { $presetCmakeCommand = $cmakeCommand @@ -160,15 +226,35 @@ foreach ($preset in $Presets) { $presetCmakeCommand = "cmake" } - & $presetCmakeCommand --preset $preset - $configureExitCode = $LASTEXITCODE + $configureExitCode = 0 + $configureLog = $null + if ($Quiet) { + $configureLog = Join-Path -Path $LogDir -ChildPath ("{0}-configure-{1}.log" -f $runId, (Limit-LogSlug (($preset -replace "[^A-Za-z0-9_.-]", "_")))) + $configureResult = Invoke-LoggedCommand ` + -Command $presetCmakeCommand ` + -Arguments @("--preset", $preset) ` + -LogPath $configureLog ` + -FailureTailLines $FailureTailLines + $configureExitCode = $configureResult.exitCode + } + else { + & $presetCmakeCommand --preset $preset + $configureExitCode = $LASTEXITCODE + } if ($configureExitCode -ne 0) { $overallExitCode = $configureExitCode - $results += [ordered]@{ + $result = [ordered]@{ preset = $preset stage = "configure" exitCode = $configureExitCode } + if ($Quiet) { + $result.log = $configureLog + if ($configureResult.Contains("failureTail")) { + $result.failureTail = $configureResult.failureTail + } + } + $results += $result continue } @@ -177,18 +263,39 @@ foreach ($preset in $Presets) { $buildArgs += @("--target", $target) } - & $presetCmakeCommand @buildArgs - $buildExitCode = $LASTEXITCODE + $buildExitCode = 0 + $buildLog = $null + if ($Quiet) { + $safeTargets = Limit-LogSlug (($Targets -join "_") -replace "[^A-Za-z0-9_.-]", "_") + $buildLog = Join-Path -Path $LogDir -ChildPath ("{0}-build-{1}-{2}.log" -f $runId, ($preset -replace "[^A-Za-z0-9_.-]", "_"), $safeTargets) + $buildResult = Invoke-LoggedCommand ` + -Command $presetCmakeCommand ` + -Arguments $buildArgs ` + -LogPath $buildLog ` + -FailureTailLines $FailureTailLines + $buildExitCode = $buildResult.exitCode + } + else { + & $presetCmakeCommand @buildArgs + $buildExitCode = $LASTEXITCODE + } if ($buildExitCode -ne 0 -and $overallExitCode -eq 0) { $overallExitCode = $buildExitCode } - $results += [ordered]@{ + $result = [ordered]@{ preset = $preset stage = "build" targets = $Targets exitCode = $buildExitCode } + if ($Quiet) { + $result.log = $buildLog + if ($buildResult.Contains("failureTail")) { + $result.failureTail = $buildResult.failureTail + } + } + $results += $result } $elapsed = [int]((Get-Date) - $started).TotalMilliseconds diff --git a/scripts/automation/quiet-validate.ps1 b/scripts/automation/quiet-validate.ps1 index e413c082..9d42abd0 100644 --- a/scripts/automation/quiet-validate.ps1 +++ b/scripts/automation/quiet-validate.ps1 @@ -13,7 +13,12 @@ param( [string]$LogDir = "out/logs/quiet-validation", [string]$IgnoreFilterFile = "", [string[]]$IgnorePattern = @(), - [int]$FailureTailLines = 0 + [int]$FailureTailLines = 0, + [switch]$IncludePlatformBuild, + [string[]]$PlatformBuildPresets = @("android-arm64", "android-x64", "android-quest-arm64", "android-focus-arm64"), + [string[]]$PlatformBuildTargets = @(), + [switch]$IncludeAppleRemote, + [string[]]$AppleRemotePresets = @("macos", "ios-simulator", "ios-device") ) $ErrorActionPreference = "Stop" @@ -179,6 +184,12 @@ function Invoke-QuietStep { $started = Get-Date $exitCode = 0 + $restoreNativeCommandPreference = $false + if (Get-Variable -Name PSNativeCommandUseErrorActionPreference -ErrorAction SilentlyContinue) { + $previousNativeCommandPreference = $PSNativeCommandUseErrorActionPreference + $PSNativeCommandUseErrorActionPreference = $false + $restoreNativeCommandPreference = $true + } try { & $Command @Arguments *> $LogPath $exitCode = $LASTEXITCODE @@ -190,6 +201,11 @@ function Invoke-QuietStep { $_ | Out-File -LiteralPath $LogPath -Append -Encoding utf8 $exitCode = 1 } + finally { + if ($restoreNativeCommandPreference) { + $PSNativeCommandUseErrorActionPreference = $previousNativeCommandPreference + } + } $elapsed = [int]((Get-Date) - $started).TotalMilliseconds $summary = Measure-Log -Path $LogPath -IgnorePatterns $IgnorePatterns @@ -212,6 +228,9 @@ $resolvedCMake = Resolve-CMakeCommand -Requested $CMakeCommand $resolvedCTest = Resolve-CTestCommand -Requested $CTestCommand -ResolvedCMake $resolvedCMake $BuildTargets = @(Expand-ArgumentList -Values $BuildTargets) $IgnorePattern = @(Expand-ArgumentList -Values $IgnorePattern) +$PlatformBuildPresets = @(Expand-ArgumentList -Values $PlatformBuildPresets) +$PlatformBuildTargets = @(Expand-ArgumentList -Values $PlatformBuildTargets) +$AppleRemotePresets = @(Expand-ArgumentList -Values $AppleRemotePresets) $ignorePatterns = Read-IgnorePatterns -FilterFile $IgnoreFilterFile -InlinePatterns $IgnorePattern New-Item -ItemType Directory -Force -Path $LogDir | Out-Null @@ -283,6 +302,76 @@ if (-not $SkipTests) { } } +if ($IncludePlatformBuild) { + $safePresets = if ($PlatformBuildPresets.Count -gt 0) { + Limit-LogSlug -Value (($PlatformBuildPresets -join "_") -replace "[^A-Za-z0-9_.-]", "_") + } else { + "defaults" + } + $log = Join-Path -Path $LogDir -ChildPath "$runId-platform-build-$safePresets.log" + $platformArgs = @( + "-ExecutionPolicy", "Bypass", + "-File", (Join-Path -Path $PSScriptRoot -ChildPath "platform-build.ps1"), + "-Quiet", + "-FailureTailLines", [string]$FailureTailLines + ) + foreach ($preset in $PlatformBuildPresets) { + $platformArgs += @("-Presets", $preset) + } + foreach ($target in $PlatformBuildTargets) { + $platformArgs += @("-Targets", $target) + } + $result = Invoke-QuietStep ` + -Name "platform-build" ` + -Command "powershell" ` + -Arguments $platformArgs ` + -LogPath $log ` + -IgnorePatterns $ignorePatterns ` + -FailureTailLines $FailureTailLines + if ($PlatformBuildPresets.Count -gt 0) { + $result.presets = $PlatformBuildPresets + } + if ($PlatformBuildTargets.Count -gt 0) { + $result.targets = $PlatformBuildTargets + } + $results += $result + if ($result.exitCode -ne 0 -and $overallExitCode -eq 0) { + $overallExitCode = $result.exitCode + } +} + +if ($IncludeAppleRemote) { + $safePresets = if ($AppleRemotePresets.Count -gt 0) { + Limit-LogSlug -Value (($AppleRemotePresets -join "_") -replace "[^A-Za-z0-9_.-]", "_") + } else { + "defaults" + } + $log = Join-Path -Path $LogDir -ChildPath "$runId-apple-remote-$safePresets.log" + $appleArgs = @( + "-ExecutionPolicy", "Bypass", + "-File", (Join-Path -Path $PSScriptRoot -ChildPath "apple-remote-build.ps1"), + "-Quiet", + "-FailureTailLines", [string]$FailureTailLines + ) + foreach ($preset in $AppleRemotePresets) { + $appleArgs += @("-Presets", $preset) + } + $result = Invoke-QuietStep ` + -Name "apple-remote-build" ` + -Command "powershell" ` + -Arguments $appleArgs ` + -LogPath $log ` + -IgnorePatterns $ignorePatterns ` + -FailureTailLines $FailureTailLines + if ($AppleRemotePresets.Count -gt 0) { + $result.presets = $AppleRemotePresets + } + $results += $result + if ($result.exitCode -ne 0 -and $overallExitCode -eq 0) { + $overallExitCode = $result.exitCode + } +} + $elapsed = [int]((Get-Date) - $started).TotalMilliseconds $summaryPath = Join-Path -Path $LogDir -ChildPath "$runId-summary.json" $payload = [ordered]@{