diff --git a/CMakeLists.txt b/CMakeLists.txt index 8f0e387..3a1c2c6 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -21,6 +21,7 @@ include(PanoPainterWarnings) include(PanoPainterSources) include(PanoPainterVersion) include(PanoPainterRuntime) +include(PanoPainterPackageTargets) if(PP_ENABLE_CLANG_TIDY) find_program(PP_CLANG_TIDY_EXE NAMES clang-tidy) diff --git a/cmake/PanoPainterPackageTargets.cmake b/cmake/PanoPainterPackageTargets.cmake new file mode 100644 index 0000000..48c8306 --- /dev/null +++ b/cmake/PanoPainterPackageTargets.cmake @@ -0,0 +1,50 @@ +find_program(PP_POWERSHELL_COMMAND NAMES pwsh powershell) + +function(pp_add_powershell_automation_target target_name) + cmake_parse_arguments(PP_PACKAGE_TARGET "" "COMMENT" "ARGUMENTS" ${ARGN}) + + if(PP_POWERSHELL_COMMAND) + add_custom_target(${target_name} + COMMAND "${PP_POWERSHELL_COMMAND}" + -NoProfile + -ExecutionPolicy Bypass + ${PP_PACKAGE_TARGET_ARGUMENTS} + WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" + COMMENT "${PP_PACKAGE_TARGET_COMMENT}" + USES_TERMINAL + VERBATIM) + else() + add_custom_target(${target_name} + COMMAND "${CMAKE_COMMAND}" -E echo "PowerShell was not found; cannot run ${target_name}." + COMMAND "${CMAKE_COMMAND}" -E false + COMMENT "${PP_PACKAGE_TARGET_COMMENT}" + VERBATIM) + endif() +endfunction() + +pp_add_powershell_automation_target(panopainter_package_readiness + COMMENT "Report package readiness blockers." + ARGUMENTS + -File "${CMAKE_CURRENT_SOURCE_DIR}/scripts/automation/package-smoke.ps1" + -ReadinessOnly) + +pp_add_powershell_automation_target(panopainter_android_standard_native_package + COMMENT "Build retained Android standard native package library." + ARGUMENTS + -File "${CMAKE_CURRENT_SOURCE_DIR}/scripts/automation/android-legacy-package-build.ps1" + -Packages standard) + +pp_add_powershell_automation_target(panopainter_android_vr_native_package_configure + COMMENT "Configure retained Android Quest/Focus native package paths." + ARGUMENTS + -File "${CMAKE_CURRENT_SOURCE_DIR}/scripts/automation/android-legacy-package-build.ps1" + -Packages quest,focus + -ConfigureOnly) + +pp_add_powershell_automation_target(panopainter_android_native_package_smoke + COMMENT "Run retained Android native package checks through package-smoke." + ARGUMENTS + -File "${CMAKE_CURRENT_SOURCE_DIR}/scripts/automation/package-smoke.ps1" + -ReadinessOnly + -AndroidNativeChecks + -PackageKinds android-standard-apk,android-quest-apk,android-focus-apk) diff --git a/docs/modernization/build-inventory.md b/docs/modernization/build-inventory.md index fa47f71..f74a832 100644 --- a/docs/modernization/build-inventory.md +++ b/docs/modernization/build-inventory.md @@ -78,6 +78,7 @@ powershell -ExecutionPolicy Bypass -File scripts\automation\android-legacy-packa 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 powershell -ExecutionPolicy Bypass -File scripts\automation\package-smoke.ps1 -ReadinessOnly -AndroidNativeChecks -PackageKinds android-standard-apk,android-quest-apk,android-focus-apk +cmake --build --preset windows-msvc-default --config Debug --target panopainter_android_native_package_smoke cmake --fresh --preset windows-clangcl-asan python scripts/dev/clangd_nav.py symbols --file src/app_core/brush_ui.h --name execute_brush python scripts/dev/clangd_nav.py symbols --file src/app_core/brush_ui.h --name-regex "execute_.*preset" @@ -184,7 +185,15 @@ powershell -ExecutionPolicy Bypass -File scripts\automation\apple-remote-build.p `scripts/dev/check_package_smoke_readiness.py`, registered as `panopainter_package_smoke_readiness_self_test`, verifies both wrappers keep the same six package kinds, blocked DEBT-0011 status, readiness-only mode, - and retained Android native-check prerequisite metadata. + retained Android native-check prerequisite metadata, and root CMake package + validation target names. +- Root CMake exposes non-default package validation targets: + `panopainter_package_readiness`, + `panopainter_android_standard_native_package`, + `panopainter_android_vr_native_package_configure`, and + `panopainter_android_native_package_smoke`. These targets call the automation + scripts from CMake but do not convert APK/AppX/Apple/WebGL package outputs to + root CMake package targets yet. - Root CMake exposes named `fuzz` and `stress` CTest presets. `fuzz` currently runs deterministic parser/serializer edge tests for binary streams, image metadata, PPI, stroke scripts, and layout XML; `stress` currently runs the diff --git a/docs/modernization/debt.md b/docs/modernization/debt.md index 8071a05..fbc4b04 100644 --- a/docs/modernization/debt.md +++ b/docs/modernization/debt.md @@ -269,6 +269,12 @@ agent or engineer to remove them without reconstructing context from chat. APK readiness matrix. The shell readiness wrapper now advertises the same retained-native validation commands, and the package-smoke self-test guards that metadata. +- 2026-06-05: DEBT-0011 was narrowed again. Root CMake now exposes + non-default package validation targets for package readiness and retained + Android native package checks. `panopainter_android_native_package_smoke` + calls the package-smoke Android native gate from CMake, validates the current + latest SDK-managed NDK/CMake pair, and still reports APK outputs as blocked + until root CMake owns real package targets. - 2026-06-04: DEBT-0036 was narrowed again. Canvas stroke commit, thumbnail, and object-draw history paths now query saved blend state through tested `pp_renderer_gl` capability-state dispatch; CanvasLayer equirect @@ -292,9 +298,9 @@ agent or engineer to remove them without reconstructing context from chat. | DEBT-0005 | Open | Modernization | Temporary local CTest harness is used before Catch2 is wired through vcpkg | `vcpkg` is not currently on PATH, but headless tests need to run now | `ctest --preset desktop-fast --build-config Debug` | Replace `tests/test_harness.h` tests with Catch2 tests once vcpkg toolchain/presets are validated | | DEBT-0007 | Open | Modernization | `vcpkg.json` and `windows-msvc-vcpkg-headless` are validated for the headless Windows component matrix, but app targets still use vendored libraries and Android/Apple triplets are not proven | Dependency migration must stay incremental while SDK/patched/vendor dependencies remain in use | `$env:VCPKG_ROOT="C:\Program Files\Microsoft Visual Studio\2022\Community\VC\vcpkg"; cmake --preset windows-msvc-vcpkg-headless`; `ctest --preset desktop-fast-vcpkg --build-config Debug` | Component targets consume vcpkg packages where reliable and desktop app, Android, and Apple triplets are validated or explicitly documented as permanent vendor exceptions | | DEBT-0008 | Open | Modernization | `windows-msvc-default` preset is used for local validation because the VS 2026 generator is not installed here | The target VS 2026 preset must remain, but this machine configures with Visual Studio 17 2022 | `cmake --preset windows-msvc-default`; `ctest --preset desktop-fast --build-config Debug` | Validate `windows-vs2026-x64` on a machine with Visual Studio 2026 installed and make it the default Windows validation preset | -| DEBT-0009 | Open | Modernization | Android root CMake validation currently builds headless targets only, while retained standard/Quest/Focus package CMake paths now have a refreshed CMake 3.10/C++23 baseline outside root CMake; automation selects the newest installed SDK Manager NDK/CMake pair before configure | Platform app entrypoints still live in legacy Gradle/CMake projects and need Phase 6 alignment | `powershell -ExecutionPolicy Bypass -File scripts\automation\platform-build.ps1 -Presets android-arm64`; `cmake --build --preset android-x64`; `cmake --build --preset android-quest-arm64`; `cmake --build --preset android-focus-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 -ReadinessOnly -AndroidNativeChecks -PackageKinds android-standard-apk,android-quest-apk,android-focus-apk` | Android standard, Quest, and Focus/Wave package targets consume shared component targets and have package smoke commands | +| DEBT-0009 | Open | Modernization | Android root CMake validation currently builds headless targets only, while retained standard/Quest/Focus package CMake paths now have a refreshed CMake 3.10/C++23 baseline outside root CMake; automation selects the newest installed SDK Manager NDK/CMake pair before configure; root CMake exposes non-default retained native package validation targets | Platform app entrypoints still live in legacy Gradle/CMake projects and need Phase 6 alignment | `powershell -ExecutionPolicy Bypass -File scripts\automation\platform-build.ps1 -Presets android-arm64`; `cmake --build --preset android-x64`; `cmake --build --preset android-quest-arm64`; `cmake --build --preset android-focus-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 -ReadinessOnly -AndroidNativeChecks -PackageKinds android-standard-apk,android-quest-apk,android-focus-apk`; `cmake --build --preset windows-msvc-default --config Debug --target panopainter_android_native_package_smoke` | Android standard, Quest, and Focus/Wave package targets consume shared component targets and have package smoke commands | | DEBT-0010 | Open | Modernization | `pp_document` is a pure layer/frame/document/undo-history model with alpha-lock metadata, snapshot construction, per-layer frame metadata, renderer-free RGBA8 face payload storage, snapshot-embedded face-payload validation, renderer-free alpha8 selection-mask storage, PPI import/export helpers, and stroke-script-to-face-payload CLI automation, but it is not yet wired to legacy `Canvas`, legacy save, or legacy action commands | Keep extraction incremental while preserving app behavior | `ctest --preset desktop-fast --build-config Debug`; `pano_cli create-document --width 64 --height 32 --layers 2`; `pano_cli load-project --path tests\data\projects\minimal-project.ppi`; `pp_document_tests`; `pp_document_ppi_import_tests`; `pp_document_ppi_export_tests`; `pano_cli_simulate_document_edits_smoke`; `pano_cli_simulate_document_export_smoke`; `pano_cli_save_document_project_roundtrip_smoke`; `pano_cli_apply_stroke_script_roundtrip_smoke`; `pano_cli_apply_stroke_script_rejects_tiny_canvas` | Legacy document behavior is represented by `pp_document` tests and the app consumes it through a boundary/facade | -| DEBT-0011 | Open | Modernization | `package-smoke` validates the Windows CMake app artifact and reports a structured package readiness matrix for Windows AppX, Android standard/Quest/Focus APKs, Apple bundles, and WebGL output; retained Android package native CMake paths are refreshed, use latest SDK-managed NDK/CMake selection, and can be run from `package-smoke.ps1 -AndroidNativeChecks`, but APK outputs are still `blocked` because root CMake package targets do not exist yet | Platform package targets are not migrated to root CMake yet | `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 -AndroidNativeChecks -PackageKinds android-standard-apk,android-quest-apk,android-focus-apk`; `python scripts/dev/check_package_smoke_readiness.py`; `bash -n scripts/automation/package-smoke.sh` | Package-smoke builds and validates Windows AppX, Android APK variants, Apple bundles, and WebGL output where local toolchains are present | +| DEBT-0011 | Open | Modernization | `package-smoke` validates the Windows CMake app artifact and reports a structured package readiness matrix for Windows AppX, Android standard/Quest/Focus APKs, Apple bundles, and WebGL output; retained Android package native CMake paths are refreshed, use latest SDK-managed NDK/CMake selection, and can be run from `package-smoke.ps1 -AndroidNativeChecks` or the root CMake `panopainter_android_native_package_smoke` target, but APK outputs are still `blocked` because root CMake package targets do not exist yet | Platform package targets are not migrated to root CMake yet | `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 -AndroidNativeChecks -PackageKinds android-standard-apk,android-quest-apk,android-focus-apk`; `cmake --build --preset windows-msvc-default --config Debug --target panopainter_android_native_package_smoke`; `python scripts/dev/check_package_smoke_readiness.py`; `bash -n scripts/automation/package-smoke.sh` | Package-smoke builds and validates Windows AppX, Android APK variants, Apple bundles, and WebGL output where local toolchains are present | | DEBT-0012 | Open | Modernization | `pp_ui_core` uses vcpkg tinyxml2 on `windows-msvc-vcpkg-headless`, but retains `pp_vendor_tinyxml2` for default and unproven platform presets | Mobile/AppX/Apple triplets and app packaging still need validation before removing the vendored fallback | `ctest --preset desktop-fast-vcpkg --build-config Debug`; `ctest --preset desktop-fast --build-config Debug`; `powershell -ExecutionPolicy Bypass -File scripts\automation\platform-build.ps1 -Presets android-arm64` | All supported presets consume vcpkg tinyxml2 or document a permanent vendored exception | | DEBT-0013 | Open | Modernization | `pp_assets`, `pp_document`, `pano_cli inspect-project`, `pano_cli load-project`, and `pano_cli save-project` validate the fixed PPI header, thumbnail/body byte layout, generated multi-layer/multi-frame PPI writing with explicit layer opacity/blend/alpha-lock/visibility metadata, per-layer frame durations, metadata-only and targeted dirty-face-payload save/load round-trips, layer/frame index, dirty-face descriptors, dirty-face PNG payload metadata, asset-level RGBA PNG payload decoding, pure document-to-PPI export, CLI document export automation, file-writing document export automation, stroke-script-generated document payload export, and decoded pixel attachment to `pp_document`, but full legacy PPI round-trip parity is not yet extracted | Full PPI save parity requires staged extraction of legacy `Canvas` serialization and image/layer payload handling | `ctest --preset desktop-fast --build-config Debug`; `pp_assets_image_pixels_tests`; `pp_assets_ppi_header_tests`; `pp_document_ppi_import_tests`; `pp_document_ppi_export_tests`; `pano_cli_inspect_project_layout_smoke`; `pano_cli_load_project_metadata_smoke`; `pano_cli_save_project_roundtrip_smoke`; `pano_cli_save_project_payload_roundtrip_smoke`; `pano_cli_simulate_document_export_smoke`; `pano_cli_save_document_project_roundtrip_smoke`; `pano_cli_apply_stroke_script_roundtrip_smoke`; `pano_cli_apply_stroke_script_rejects_tiny_canvas` | Full PPI load/save fixtures cover thumbnails, decoded layer face payloads attached to documents, frames, corrupt payloads, dirty-face payload saving, arbitrary legacy canvas payload/layout combinations, and legacy app round-trip compatibility | | DEBT-0014 | Open | Modernization | `windows-clangcl-asan` now configures as a headless Ninja/clang-cl preset and uses the release MSVC runtime required by ASan, but local builds still fail because installed clang-cl 18.1.8 is paired with VS 2026-preview STL headers that require Clang 20 or newer | Sanitizer validation should be local and repeatable, but this machine's compiler/header pairing is incompatible | `cmake --fresh --preset windows-clangcl-asan`; `cmake --build --preset windows-clangcl-asan --target pp_foundation` | Install/use Clang 20+ with the VS 2026 STL, or point the preset at a compatible VS 2022 toolchain, then make `platform-build.ps1 -Presets windows-clangcl-asan` pass for the headless matrix | diff --git a/docs/modernization/roadmap.md b/docs/modernization/roadmap.md index 91cba33..c823ca1 100644 --- a/docs/modernization/roadmap.md +++ b/docs/modernization/roadmap.md @@ -1392,9 +1392,13 @@ cheap package blocker inventory without building an app artifact, and readiness matrices aligned. The PowerShell wrapper can also run the retained Android native package checks through `-AndroidNativeChecks`, reporting the standard `native-lib` build plus Quest/Focus configure checks next to the APK -blocker matrix. 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. +blocker matrix. Root CMake now exposes non-default package validation targets +for package readiness and retained Android native checks: +`panopainter_package_readiness`, `panopainter_android_standard_native_package`, +`panopainter_android_vr_native_package_configure`, and +`panopainter_android_native_package_smoke`. 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 @@ -2384,7 +2388,11 @@ Results: -ReadinessOnly -AndroidNativeChecks -PackageKinds android-standard-apk,android-quest-apk,android-focus-apk` now runs those retained native checks from the package-smoke surface while keeping APK - readiness blocked on root CMake package-target migration. + readiness blocked on root CMake package-target migration. Root CMake now has + named package validation targets for that same retained Android native gate; + `cmake --build --preset windows-msvc-default --config Debug --target + panopainter_android_native_package_smoke` validates the latest SDK-managed + NDK/CMake pair and reports the still-blocked APK package state. - Desktop VR drawing now routes generic OpenGL scissor/depth/blend state, blend/depth state snapshots and restores, depth clears, active texture units, and fallback 2D texture unbinds through tested renderer GL backend dispatch; diff --git a/scripts/dev/check_package_smoke_readiness.py b/scripts/dev/check_package_smoke_readiness.py index f8d9292..eee0375 100644 --- a/scripts/dev/check_package_smoke_readiness.py +++ b/scripts/dev/check_package_smoke_readiness.py @@ -18,6 +18,13 @@ EXPECTED_PACKAGE_KINDS = [ "webgl", ] +EXPECTED_CMAKE_PACKAGE_TARGETS = [ + "panopainter_package_readiness", + "panopainter_android_standard_native_package", + "panopainter_android_vr_native_package_configure", + "panopainter_android_native_package_smoke", +] + def repo_root() -> Path: return Path(__file__).resolve().parents[2] @@ -65,6 +72,8 @@ def main() -> int: "package-smoke.ps1": r"retained-native-cmake-check", "package-smoke.sh": r"retained-native-cmake-check", }) + cmake_package_module = (root / "cmake" / "PanoPainterPackageTargets.cmake").read_text(encoding="utf-8") + root_cmake = (root / "CMakeLists.txt").read_text(encoding="utf-8") missing = { "package-smoke.ps1": [kind for kind in expected if kind not in ps_kinds], @@ -84,6 +93,10 @@ def main() -> int: retained_android_native_complete = { name: count >= 3 for name, count in retained_android_native_counts.items() } + cmake_package_targets_present = { + target: target in cmake_package_module for target in EXPECTED_CMAKE_PACKAGE_TARGETS + } + cmake_package_module_included = "include(PanoPainterPackageTargets)" in root_cmake ok = ( all(not values for values in missing.values()) @@ -92,6 +105,8 @@ def main() -> int: and all(blocked_complete.values()) and all(readiness_mode_present.values()) and all(retained_android_native_complete.values()) + and all(cmake_package_targets_present.values()) + and cmake_package_module_included ) print(json.dumps({ @@ -107,6 +122,8 @@ def main() -> int: "blockedComplete": blocked_complete, "readinessModePresent": readiness_mode_present, "retainedAndroidNativeComplete": retained_android_native_complete, + "cmakePackageTargetsPresent": cmake_package_targets_present, + "cmakePackageModuleIncluded": cmake_package_module_included, }, separators=(",", ":"))) return 0 if ok else 1