diff --git a/AGENTS.md b/AGENTS.md index a56f97b..651038b 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -54,6 +54,15 @@ Useful targeted pattern: ctest --preset desktop-fast --build-config Debug -R "pp_app_core|pano_cli_plan" --output-on-failure ``` +Apple compile validation runs through the Mac mini SSH alias `panopainter-mac`: + +```powershell +powershell -ExecutionPolicy Bypass -File scripts\automation\apple-remote-build.ps1 -Presets macos,ios-simulator,ios-device +``` + +This is a headless component/test/tool compile gate for macOS, iOS simulator, +and iOS device. Signed Apple bundles remain tracked in the debt log. + If MSVC reports corrupt debug information or stale PDB/object errors, clean the generated build tree target before judging source changes: diff --git a/CMakeLists.txt b/CMakeLists.txt index 2c241b0..77aa735 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -50,6 +50,13 @@ target_compile_features(pp_project_options INTERFACE cxx_std_23) add_library(pp_project_warnings INTERFACE) pp_configure_project_warnings(pp_project_warnings) +if(CMAKE_SYSTEM_NAME STREQUAL "iOS") + set(CMAKE_XCODE_ATTRIBUTE_PRODUCT_BUNDLE_IDENTIFIER + "com.omigamedev.panopainter.$(PRODUCT_NAME:rfc1034identifier)") + set(CMAKE_XCODE_ATTRIBUTE_CODE_SIGNING_ALLOWED "NO") + set(CMAKE_XCODE_ATTRIBUTE_CODE_SIGNING_REQUIRED "NO") +endif() + if(PP_USE_VCPKG_TINYXML2) find_package(tinyxml2 CONFIG REQUIRED) add_library(pp_xml_tinyxml2 INTERFACE) diff --git a/docs/modernization/build-inventory.md b/docs/modernization/build-inventory.md index fbc224d..54ceb8c 100644 --- a/docs/modernization/build-inventory.md +++ b/docs/modernization/build-inventory.md @@ -84,6 +84,7 @@ python scripts/dev/clangd_nav.py references --file src/app_core/brush_ui.h --lin 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 ``` Known local toolchain state: @@ -122,6 +123,23 @@ Known local toolchain state: results or `--allow-incomplete-references` for explicitly current-translation-unit-only results, and do not treat incomplete references as proof that no other users exist. +- Apple headless compile validation runs on the local Mac mini SSH alias + `panopainter-mac` with user `builder`. The host uses a Gitea SSH key for + `ssh://git@git.omar.synology.me:3022/omar/panopainter.git`, Homebrew + CMake/Ninja/Git, and full Xcode selected per command with + `DEVELOPER_DIR=/Applications/Xcode.app/Contents/Developer`. The repeatable + Windows-side command is: + +```powershell +powershell -ExecutionPolicy Bypass -File scripts\automation\apple-remote-build.ps1 -Presets macos,ios-simulator,ios-device +``` + + The wrapper updates `~/Dev/panopainter`, initializes the source submodules + required by the headless CMake matrix, and delegates to + `scripts/automation/platform-build.sh`. macOS, iOS simulator, and iOS device + currently validate shared component/test/tool targets only; signed Apple app + bundles remain tracked by DEBT-0011 and the iOS compile-only signing shortcut + is tracked by DEBT-0059. - Android standard arm64/x64, Quest arm64, and Focus/Wave arm64 headless configure/build pass through root CMake and the `platform-build` automation wrapper defaults for `pp_foundation`, `pp_assets`, diff --git a/docs/modernization/debt.md b/docs/modernization/debt.md index 622461b..9457437 100644 --- a/docs/modernization/debt.md +++ b/docs/modernization/debt.md @@ -35,6 +35,13 @@ agent or engineer to remove them without reconstructing context from chat. blocker matrix without requiring an app build first, and `panopainter_package_smoke_readiness_self_test` guards package-kind parity across both wrappers. Package target migration remains open. +- 2026-06-05: DEBT-0004 was narrowed for Apple compile coverage. The Mac mini + build host `panopainter-mac` now pulls from Gitea over SSH, uses Homebrew + CMake/Ninja/Git plus full Xcode through `DEVELOPER_DIR`, and + `scripts/automation/apple-remote-build.ps1` drives the `macos`, + `ios-simulator`, and `ios-device` root CMake headless component matrix. + Apple app bundle/signing/package migration remains open under DEBT-0011 and + DEBT-0059. - 2026-06-05: DEBT-0022 was narrowed. `pp_app_core` now owns tested onion-skin frame range and alpha falloff planning, and live `NodeCanvas` panorama drawing consumes that helper instead of open-coding frame clamping @@ -289,6 +296,7 @@ agent or engineer to remove them without reconstructing context from chat. | DEBT-0056 | Open | Modernization | `src/asset.h` now forward-declares Android asset-manager types and uses `Asset::set_android_asset_manager` instead of public mutable manager state, but retained `Asset` still stores Android asset handles and `src/asset.cpp` still performs Android `AAssetManager` reads directly; the current `android-arm64` root preset is headless and does not expose `pp_legacy_assets_io` | Reduce legacy asset I/O header coupling without rewriting Android asset loading before the asset manager/storage boundary exists | Windows app build; `cmake --build --preset android-arm64 --target pp_assets`; Android package smoke once package builds consume shared targets | Android asset loading is owned by injected asset storage/platform services or `pp_assets` file providers, with no static Android asset manager on `Asset` | | DEBT-0057 | Open | Modernization | Default canvas allocation size now dispatches through `PlatformServices::default_canvas_resolution`, removing the `CANVAS_RES` platform macro from `src/canvas.h`, but WebGL's retained 512 default still lives in `src/platform_legacy/legacy_platform_services.cpp` until the Web shell owns injected services | Preserve WebGL memory behavior while moving canvas creation policy out of shared canvas headers and into the platform boundary | `pp_platform_api_tests`; `ctest --preset desktop-fast --build-config Debug -R pp_platform_api_tests`; Windows app build; WebGL package smoke once root Web build exists | Default canvas resolution is owned by injected `pp_platform_*` services for every supported platform, with no WebGL branch in the legacy fallback | | DEBT-0058 | Open | Modernization | App-level progress/message/input dialog metadata, including message-dialog OK/cancel captions, now consumes pure `pp_app_core` through `App::show_progress`, `App::message_box`, `App::input_box`, `pano_cli plan-app-dialog`, and `pp_app_core_app_dialog_tests`; live execution is centralized in `src/legacy_app_dialog_services.*`, but the bridge still creates retained `NodeProgressBar`, `NodeMessageBox`, and `NodeInputBox` instances and inserts them into the legacy layout tree | Preserve current app-shell dialog behavior while moving shared dialog policy toward UI/app services | `pp_app_core_app_dialog_tests`; `pano_cli plan-app-dialog --kind progress --total -4`; `pano_cli plan-app-dialog --kind message --cancel`; `pano_cli plan-app-dialog --kind input --ok-caption Save`; `ctest --preset desktop-fast --build-config Debug`; Windows app build | Progress/message/input dialog creation, callback wiring, layout insertion, lifetime ownership, and headless automation are owned by injected app/UI services with `App` methods acting only as adapters | +| DEBT-0059 | Open | Modernization | iOS root CMake headless builds assign generated bundle identifiers and disable code signing for executable test/tool targets | The current Apple gate is compile validation for shared component targets; signed iOS app/package validation is not migrated to root CMake yet | `powershell -ExecutionPolicy Bypass -File scripts\automation\apple-remote-build.ps1 -Presets macos,ios-simulator,ios-device`; `sh scripts/automation/platform-build.sh "ios-device"` on `panopainter-mac` | Root CMake owns the signed Apple app/package targets, package-smoke validates Apple bundles where signing material is available, and headless iOS test/tool targets are either excluded from signed package builds or use explicit test-runner signing policy | ## Closed Debt diff --git a/docs/modernization/roadmap.md b/docs/modernization/roadmap.md index a3a225b..670609f 100644 --- a/docs/modernization/roadmap.md +++ b/docs/modernization/roadmap.md @@ -1391,6 +1391,14 @@ cheap package blocker inventory without building an app artifact, and readiness matrices aligned. App/package entrypoints still need to consume shared targets and remain covered by debt until package validation is migrated from legacy package projects to root CMake. +Apple compile validation now runs on the local Mac mini SSH host +`panopainter-mac` through `scripts/automation/apple-remote-build.ps1`. The host +uses Homebrew CMake/Ninja/Git plus full Xcode via `DEVELOPER_DIR`, pulls the +modernization branch from Gitea, initializes the source submodules needed by the +current headless matrix, and builds `macos`, `ios-simulator`, and `ios-device`. +The iOS device compile gate assigns generated bundle identifiers and disables +code signing for test/tool executables under DEBT-0059; signed Apple app bundle +and package-smoke migration remains open under DEBT-0011. Implementation tasks: @@ -1534,6 +1542,7 @@ powershell -ExecutionPolicy Bypass -File scripts\automation\platform-build.ps1 - powershell -ExecutionPolicy Bypass -File scripts\automation\package-smoke.ps1 -Preset windows-msvc-default -Configuration Debug powershell -ExecutionPolicy Bypass -File scripts\automation\package-smoke.ps1 -ReadinessOnly cmake --fresh --preset windows-clangcl-asan +powershell -ExecutionPolicy Bypass -File scripts\automation\apple-remote-build.ps1 -Presets macos,ios-simulator,ios-device ``` Results: diff --git a/scripts/automation/apple-remote-build.ps1 b/scripts/automation/apple-remote-build.ps1 new file mode 100644 index 0000000..4332110 --- /dev/null +++ b/scripts/automation/apple-remote-build.ps1 @@ -0,0 +1,91 @@ +[CmdletBinding()] +param( + [string]$HostName = "panopainter-mac", + [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") +) + +$ErrorActionPreference = "Stop" + +function Join-RemoteArgument { + param([string[]]$Values) + + $expanded = @() + foreach ($value in $Values) { + foreach ($part in ($value -split ",")) { + $trimmed = $part.Trim() + if ($trimmed.Length -gt 0) { + $expanded += $trimmed + } + } + } + return ($expanded -join " ") +} + +function ConvertTo-ShellSingleQuoted { + param([string]$Value) + + return "'" + ($Value -replace "'", "'\\''") + "'" +} + +$presetArgument = Join-RemoteArgument -Values $Presets +$remoteDirectoryLiteral = ConvertTo-ShellSingleQuoted -Value $RemoteDirectory +$repositoryLiteral = ConvertTo-ShellSingleQuoted -Value $RepositoryUrl +$branchLiteral = ConvertTo-ShellSingleQuoted -Value $Branch +$presetLiteral = ConvertTo-ShellSingleQuoted -Value $presetArgument + +$remoteScript = @" +set -eu +export PATH="/opt/homebrew/bin:/usr/local/bin:`$HOME/tools/bin:`$PATH" +export DEVELOPER_DIR="/Applications/Xcode.app/Contents/Developer" + +remote_dir=$remoteDirectoryLiteral +repository_url=$repositoryLiteral +branch_name=$branchLiteral +presets=$presetLiteral + +case "$remote_dir" in + "~/"*) remote_dir="$HOME/${remote_dir#~/}" ;; +esac + +mkdir -p "`$(dirname "`$remote_dir")" +if [ ! -d "`$remote_dir/.git" ]; then + git clone "`$repository_url" "`$remote_dir" +fi + +cd "`$remote_dir" +git fetch origin +git checkout "`$branch_name" +git pull --ff-only origin "`$branch_name" + +git submodule update --init --recursive \ + libs/tinyxml2 \ + libs/glm \ + libs/stb/stb \ + libs/yoga \ + libs/poly2tri \ + libs/base64 \ + libs/sqlite3 \ + libs/nanort \ + libs/hash-library \ + libs/fmt \ + libs/glad \ + libs/tinyfiledialogs + +mkdir -p out/logs +log="out/logs/apple-platform-build-`$(date +%Y%m%d-%H%M%S).log" +set +e +sh ./scripts/automation/platform-build.sh "`$presets" > "`$log" 2>&1 +exit_code=`$? +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" +exit "`$exit_code" +"@ + +$remoteScript | & ssh -o BatchMode=yes $HostName "sh -s" +exit $LASTEXITCODE