Use latest Android SDK toolchain

This commit is contained in:
2026-06-05 12:28:47 +02:00
parent ac4fef8346
commit c761cd39fd
11 changed files with 319 additions and 15 deletions

View File

@@ -4,6 +4,8 @@
cmake_minimum_required(VERSION 3.10)
project(PanoPainterAndroidNative LANGUAGES C CXX)
include(../cmake/PanoPainterAndroidLegacyCompat.cmake)
link_directories(

View File

@@ -4,6 +4,8 @@
cmake_minimum_required(VERSION 3.10)
project(PanoPainterFocusNative LANGUAGES C CXX)
include(../cmake/PanoPainterAndroidLegacyCompat.cmake)
# build native_app_glue as a static lib

View File

@@ -4,6 +4,8 @@
cmake_minimum_required(VERSION 3.10)
project(PanoPainterQuestNative LANGUAGES C CXX)
include(../cmake/PanoPainterAndroidLegacyCompat.cmake)
# build native_app_glue as a static lib

View File

@@ -73,10 +73,8 @@ powershell -ExecutionPolicy Bypass -File scripts\automation\platform-build.ps1 -
ctest --preset desktop-fast-vcpkg --build-config Debug
cmake --preset android-arm64
powershell -ExecutionPolicy Bypass -File scripts\automation\platform-build.ps1 -Presets android-arm64
cmake -S android/android -B out/build/android-legacy-standard-arm64 -G Ninja -DCMAKE_TOOLCHAIN_FILE="$env:ANDROID_NDK_HOME\build\cmake\android.toolchain.cmake" -DANDROID_ABI=arm64-v8a -DANDROID_PLATFORM=android-23
cmake --build out/build/android-legacy-standard-arm64 --target native-lib
cmake -S android/quest -B out/build/android-legacy-quest-arm64 -G Ninja -DCMAKE_TOOLCHAIN_FILE="$env:ANDROID_NDK_HOME\build\cmake\android.toolchain.cmake" -DANDROID_ABI=arm64-v8a -DANDROID_PLATFORM=android-23
cmake -S android/focus -B out/build/android-legacy-focus-arm64 -G Ninja -DCMAKE_TOOLCHAIN_FILE="$env:ANDROID_NDK_HOME\build\cmake\android.toolchain.cmake" -DANDROID_ABI=arm64-v8a -DANDROID_PLATFORM=android-23
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
powershell -ExecutionPolicy Bypass -File scripts\automation\package-smoke.ps1 -ReadinessOnly
cmake --fresh --preset windows-clangcl-asan
@@ -98,7 +96,12 @@ Known local toolchain state:
- Bundled vcpkg: `C:\Program Files\Microsoft Visual Studio\2022\Community\VC\vcpkg`
(`vcpkg version` reports 2025-11-19)
- Android SDK: `C:\Users\omara\AppData\Local\Android\Sdk`
- Android NDK: `C:\Users\omara\AppData\Local\Android\Sdk\ndk\29.0.14206865`
- Android NDK: latest SDK Manager package selected by
`scripts/automation/android-sdk-env.ps1`; currently
`C:\Users\omara\AppData\Local\Android\Sdk\ndk\30.0.14904198`
- Android CMake: latest SDK Manager package selected by
`scripts/automation/android-sdk-env.ps1`; currently
`C:\Users\omara\AppData\Local\Android\Sdk\cmake\4.1.2`
- clang-cl: `C:\Program Files\LLVM\bin\clang-cl.exe` reports 18.1.8, but the
selected VS 2026-preview STL expects Clang 20 or newer; see DEBT-0014 before
treating `windows-clangcl-asan` as a passing sanitizer gate.

View File

@@ -256,6 +256,12 @@ agent or engineer to remove them without reconstructing context from chat.
The standard arm64 `native-lib` package target builds and links directly;
Quest and Focus package CMake paths configure with the current Yoga source
list. APK/package migration into root CMake remains open.
- 2026-06-05: DEBT-0009 was narrowed again. Android automation now selects the
newest installed SDK Manager NDK/CMake pair through
`scripts/automation/android-sdk-env.*`, reports that toolchain in structured
wrapper output, and the current host installed/validated NDK `30.0.14904198`
plus CMake `4.1.2`. Root Android `pp_assets`, retained standard
`native-lib`, and retained Quest/Focus configure gates pass with that pair.
- 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
@@ -279,9 +285,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; standard arm64 `native-lib` builds directly and Quest/Focus package paths 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`; `cmake --build out/build/android-legacy-standard-arm64 --target native-lib`; Quest/Focus retained package configure checks | 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 | 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` | 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 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`; `bash -n scripts/automation/package-smoke.sh`; retained Android standard `native-lib` build and Quest/Focus configure checks | 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 and use latest SDK-managed NDK/CMake selection, 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`; `bash -n scripts/automation/package-smoke.sh`; retained Android standard `native-lib` build and Quest/Focus configure checks | 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 |
@@ -325,8 +331,8 @@ agent or engineer to remove them without reconstructing context from chat.
| DEBT-0053 | Open | Modernization | Prepared-file writable target selection and prepared-file export-dialog policy now dispatch through `PlatformServices`; iOS temporary-file and WebGL data-path target planning live in tested `pp_platform_api::platform_policy`, but retained iOS/Web save/download handoff execution still lives in `src/platform_legacy/legacy_platform_services.*` | Preserve mobile/Web export handoff behavior while platform shells are extracted incrementally | `pp_platform_api_tests`; `ctest --preset desktop-fast --build-config Debug`; Windows app build; Apple/Web package smoke once root package builds exist | Prepared-file target selection, export-dialog policy, and save/download handoff are owned by injected platform services with no legacy adapter branch |
| DEBT-0054 | Open | Modernization | Layout XML file read/reload decisions now consume `pp_platform_api::plan_asset_file_load`; platform-family reload behavior lives in tested `pp_platform_api::platform_policy` and pure probed planning, but the live wrapper still performs direct `stat` probing for Windows/macOS mtime reload checks until platform storage/file-watch services exist | Preserve current layout hot-reload and mobile/Web single-load behavior while removing platform guards from the shared `LayoutManager` parser | `pp_platform_api_tests`; `ctest --preset desktop-fast --build-config Debug -R pp_platform_api_tests`; Windows app build | Layout reload decisions are owned by injected platform storage/file-watch services or an asset manager boundary with platform-specific file watching removed from compile-time helpers |
| DEBT-0055 | Open | Modernization | `src/app.h` now forward-declares retained iOS/macOS/Android/Linux/Web platform handles instead of including platform SDK headers, and full SDK includes are isolated in `src/platform_legacy/legacy_platform_services.cpp`, but the `App` singleton still stores those platform handles directly | Reduce central header platform coupling incrementally without rewriting non-Windows platform entrypoints before Phase 6 | Windows app build; Apple/Android/Linux/Web package smoke once platform root builds are active | Platform handles are owned by injected `pp_platform_*` shell state or services, and `App` has no platform SDK handle fields or platform conditional members |
| DEBT-0056 | Open | Modernization | `src/asset.h` is now Android-SDK-free and uses opaque Android asset handles behind `Asset::set_android_asset_manager`, but retained `Asset` still owns a static Android asset-manager bridge 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`, though the retained Android standard package `native-lib` now builds through its refreshed C++23 CMake path | Reduce legacy asset I/O header coupling without rewriting Android asset loading before the asset manager/storage boundary exists | Windows app build; `powershell -ExecutionPolicy Bypass -File scripts\automation\platform-build.ps1 -Presets android-arm64 -Targets pp_assets`; `cmake --build out/build/android-legacy-standard-arm64 --target native-lib` | 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-0060 | Open | Modernization | Retained Android package CMake generates a patched `nanort.h` overlay in the build tree for `native-lib` instead of modifying the `libs/nanort` submodule | Current NDK/Clang rejects `TriangleSAHPred::operator=` assigning to a `const size_t` member, but the retained grid/lightmap path still includes `nanort` before that dependency is replaced or updated | `cmake --build out/build/android-legacy-standard-arm64 --target native-lib`; Quest/Focus retained package configure checks; Windows app build | Update/replace `nanort`, move grid/lightmap baking behind a component that owns its dependency, or retire the retained Android package CMake path so no generated vendor overlay is required |
| DEBT-0056 | Open | Modernization | `src/asset.h` is now Android-SDK-free and uses opaque Android asset handles behind `Asset::set_android_asset_manager`, but retained `Asset` still owns a static Android asset-manager bridge 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`, though the retained Android standard package `native-lib` now builds through its refreshed C++23 CMake path | Reduce legacy asset I/O header coupling without rewriting Android asset loading before the asset manager/storage boundary exists | Windows app build; `powershell -ExecutionPolicy Bypass -File scripts\automation\platform-build.ps1 -Presets android-arm64 -Targets pp_assets`; `powershell -ExecutionPolicy Bypass -File scripts\automation\android-legacy-package-build.ps1 -Packages standard` | 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-0060 | Open | Modernization | Retained Android package CMake generates a patched `nanort.h` overlay in the build tree for `native-lib` instead of modifying the `libs/nanort` submodule | Current SDK Manager NDK/Clang rejects `TriangleSAHPred::operator=` assigning to a `const size_t` member, but the retained grid/lightmap path still includes `nanort` before that dependency is replaced or updated | `powershell -ExecutionPolicy Bypass -File scripts\automation\android-legacy-package-build.ps1 -Packages standard`; Quest/Focus retained package configure checks; Windows app build | Update/replace `nanort`, move grid/lightmap baking behind a component that owns its dependency, or retire the retained Android package CMake path so no generated vendor overlay is required |
| 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`; WebGL's retained 512 default now lives in tested `pp_platform_api::platform_policy`, but the Web shell still reaches it through the legacy platform fallback until injected Web services own the policy | 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 |

View File

@@ -1417,7 +1417,11 @@ monolithically, and share a generated `nanort` compatibility overlay from
`android/cmake/PanoPainterAndroidLegacyCompat.cmake` instead of dirtying the
vendor submodule. The standard package `native-lib` arm64 target now compiles
and links with the current NDK; Quest and Focus configure with the aligned Yoga
source list and their SDK imported-library paths.
source list and their SDK imported-library paths. Android automation now
discovers the newest installed SDK-managed NDK and CMake package before
configuring Android presets or retained package paths; on the current Windows
host that selects NDK `30.0.14904198` and CMake `4.1.2` after installing the
latest NDK through `sdkmanager`.
Implementation tasks:
@@ -2371,6 +2375,9 @@ Results:
configures/builds `native-lib` directly for arm64 using C++23 and the shared
modern component source set, while Quest and Focus package CMake paths
configure with the same compatibility helper and current Yoga source list.
The Android platform-build wrapper and retained package helper now select the
newest installed SDK Manager NDK/CMake pair automatically and report the
selected versions in their structured output.
- 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;

View File

@@ -0,0 +1,103 @@
[CmdletBinding()]
param(
[string[]]$Packages = @("standard"),
[switch]$ConfigureOnly
)
$ErrorActionPreference = "Stop"
. "$PSScriptRoot\android-sdk-env.ps1"
function Expand-ArgumentList {
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
}
$Packages = @(Expand-ArgumentList -Values $Packages)
$toolchain = Set-AndroidSdkToolchainEnvironment
$packageMap = @{
standard = "android/android"
quest = "android/quest"
focus = "android/focus"
}
$started = Get-Date
$results = @()
$overallExitCode = 0
foreach ($package in $Packages) {
if (!$packageMap.ContainsKey($package)) {
throw "Unknown Android package '$package'. Expected one of: standard, quest, focus."
}
$sourceDir = $packageMap[$package]
$buildDir = "out/build/android-legacy-$package-arm64"
$toolchainFile = Join-Path $toolchain.ndkPath "build\cmake\android.toolchain.cmake"
$configureArgs = @(
"-S", $sourceDir,
"-B", $buildDir,
"-G", "Ninja",
"-DCMAKE_TOOLCHAIN_FILE=$toolchainFile",
"-DANDROID_ABI=arm64-v8a",
"-DANDROID_PLATFORM=android-23"
)
& $toolchain.cmakeCommand @configureArgs
$configureExitCode = $LASTEXITCODE
if ($configureExitCode -ne 0) {
if ($overallExitCode -eq 0) {
$overallExitCode = $configureExitCode
}
$results += [ordered]@{
package = $package
stage = "configure"
exitCode = $configureExitCode
}
continue
}
if ($ConfigureOnly) {
$results += [ordered]@{
package = $package
stage = "configure"
exitCode = 0
}
continue
}
& $toolchain.cmakeCommand --build $buildDir --target native-lib
$buildExitCode = $LASTEXITCODE
if ($buildExitCode -ne 0 -and $overallExitCode -eq 0) {
$overallExitCode = $buildExitCode
}
$results += [ordered]@{
package = $package
stage = "build"
target = "native-lib"
exitCode = $buildExitCode
}
}
$elapsed = [int]((Get-Date) - $started).TotalMilliseconds
[ordered]@{
command = "android-legacy-package-build"
exitCode = $overallExitCode
elapsedMs = $elapsed
androidToolchain = $toolchain
results = $results
} | ConvertTo-Json -Compress -Depth 6
exit $overallExitCode

View File

@@ -0,0 +1,66 @@
[CmdletBinding()]
param()
$ErrorActionPreference = "Stop"
function Get-AndroidSdkRoot {
$candidates = @(
$env:ANDROID_SDK_ROOT,
$env:ANDROID_HOME,
(Join-Path $env:LOCALAPPDATA "Android\Sdk")
)
foreach ($candidate in $candidates) {
if ($candidate -and (Test-Path -LiteralPath $candidate -PathType Container)) {
return (Resolve-Path -LiteralPath $candidate).Path
}
}
throw "Android SDK root was not found. Install command-line tools or set ANDROID_SDK_ROOT."
}
function Get-LatestAndroidSdkPackageDirectory {
param(
[Parameter(Mandatory=$true)][string]$SdkRoot,
[Parameter(Mandatory=$true)][string]$PackageName
)
$packageRoot = Join-Path $SdkRoot $PackageName
if (!(Test-Path -LiteralPath $packageRoot -PathType Container)) {
throw "Android SDK package directory not found: $packageRoot"
}
$packages = @(Get-ChildItem -LiteralPath $packageRoot -Directory |
Where-Object { $_.Name -match '^\d+(\.\d+)*$' } |
Sort-Object { [version]$_.Name } -Descending)
if ($packages.Count -eq 0) {
throw "No installed Android SDK package versions found under $packageRoot"
}
return $packages[0]
}
function Set-AndroidSdkToolchainEnvironment {
$sdkRoot = Get-AndroidSdkRoot
$ndk = Get-LatestAndroidSdkPackageDirectory -SdkRoot $sdkRoot -PackageName "ndk"
$cmake = Get-LatestAndroidSdkPackageDirectory -SdkRoot $sdkRoot -PackageName "cmake"
$cmakeCommand = Join-Path $cmake.FullName "bin\cmake.exe"
if (!(Test-Path -LiteralPath $cmakeCommand -PathType Leaf)) {
throw "Android SDK CMake executable not found: $cmakeCommand"
}
$env:ANDROID_HOME = $sdkRoot
$env:ANDROID_SDK_ROOT = $sdkRoot
$env:ANDROID_NDK_HOME = $ndk.FullName
$env:ANDROID_NDK_ROOT = $ndk.FullName
return [ordered]@{
sdkRoot = $sdkRoot
ndkVersion = $ndk.Name
ndkPath = $ndk.FullName
cmakeVersion = $cmake.Name
cmakeCommand = $cmakeCommand
}
}

View File

@@ -0,0 +1,78 @@
#!/usr/bin/env sh
android_sdk_root() {
if [ -n "${ANDROID_SDK_ROOT:-}" ] && [ -d "$ANDROID_SDK_ROOT" ]; then
printf '%s\n' "$ANDROID_SDK_ROOT"
return 0
fi
if [ -n "${ANDROID_HOME:-}" ] && [ -d "$ANDROID_HOME" ]; then
printf '%s\n' "$ANDROID_HOME"
return 0
fi
if [ -n "${LOCALAPPDATA:-}" ]; then
local_sdk="$LOCALAPPDATA/Android/Sdk"
if command -v cygpath >/dev/null 2>&1; then
local_sdk="$(cygpath -u "$local_sdk")"
fi
if [ -d "$local_sdk" ]; then
printf '%s\n' "$local_sdk"
return 0
fi
fi
if [ -d "$HOME/Android/Sdk" ]; then
printf '%s\n' "$HOME/Android/Sdk"
return 0
fi
return 1
}
latest_android_package_dir() {
root="$1"
package="$2"
package_root="$root/$package"
[ -d "$package_root" ] || return 1
latest="$(
for dir in "$package_root"/*; do
[ -d "$dir" ] || continue
version="${dir##*/}"
printf '%s\n' "$version"
done | grep -E '^[0-9]+(\.[0-9]+)*$' | sort -t . -k 1,1n -k 2,2n -k 3,3n -k 4,4n | tail -n 1
)"
[ -n "$latest" ] || return 1
printf '%s/%s\n' "$package_root" "$latest"
}
set_android_sdk_toolchain_environment() {
sdk_root="$(android_sdk_root)" || {
printf '%s\n' "Android SDK root was not found. Install command-line tools or set ANDROID_SDK_ROOT." >&2
return 1
}
ndk_dir="$(latest_android_package_dir "$sdk_root" ndk)" || {
printf '%s\n' "No installed Android NDK package was found under $sdk_root/ndk." >&2
return 1
}
cmake_dir="$(latest_android_package_dir "$sdk_root" cmake)" || {
printf '%s\n' "No installed Android CMake package was found under $sdk_root/cmake." >&2
return 1
}
cmake_command="$cmake_dir/bin/cmake"
[ -x "$cmake_command" ] || {
printf '%s\n' "Android SDK CMake executable not found: $cmake_command" >&2
return 1
}
export ANDROID_HOME="$sdk_root"
export ANDROID_SDK_ROOT="$sdk_root"
export ANDROID_NDK_HOME="$ndk_dir"
export ANDROID_NDK_ROOT="$ndk_dir"
export ANDROID_CMAKE_COMMAND="$cmake_command"
export ANDROID_NDK_VERSION="${ndk_dir##*/}"
export ANDROID_CMAKE_VERSION="${cmake_dir##*/}"
}

View File

@@ -96,12 +96,25 @@ function Expand-ArgumentList {
$Presets = @(Expand-ArgumentList -Values $Presets)
$Targets = @(Expand-ArgumentList -Values $Targets)
$cmakeCommand = "cmake"
$androidToolchain = $null
if ($Presets | Where-Object { $_ -like "android-*" }) {
. "$PSScriptRoot\android-sdk-env.ps1"
$androidToolchain = Set-AndroidSdkToolchainEnvironment
$cmakeCommand = $androidToolchain.cmakeCommand
}
$started = Get-Date
$results = @()
$overallExitCode = 0
foreach ($preset in $Presets) {
& cmake --preset $preset
$presetCmakeCommand = $cmakeCommand
if ($androidToolchain -and $preset -notlike "android-*") {
$presetCmakeCommand = "cmake"
}
& $presetCmakeCommand --preset $preset
$configureExitCode = $LASTEXITCODE
if ($configureExitCode -ne 0) {
$overallExitCode = $configureExitCode
@@ -118,7 +131,7 @@ foreach ($preset in $Presets) {
$buildArgs += @("--target", $target)
}
& cmake @buildArgs
& $presetCmakeCommand @buildArgs
$buildExitCode = $LASTEXITCODE
if ($buildExitCode -ne 0 -and $overallExitCode -eq 0) {
$overallExitCode = $buildExitCode
@@ -137,6 +150,7 @@ $elapsed = [int]((Get-Date) - $started).TotalMilliseconds
command = "platform-build"
exitCode = $overallExitCode
elapsedMs = $elapsed
androidToolchain = $androidToolchain
results = $results
} | ConvertTo-Json -Compress -Depth 6

View File

@@ -6,6 +6,16 @@ shift || true
targets="${*:-pp_foundation pp_assets pp_paint pp_document pp_renderer_api pp_renderer_gl pp_paint_renderer pp_ui_core pp_platform_api pp_app_core pano_cli pp_foundation_binary_stream_tests pp_foundation_event_tests pp_foundation_log_tests pp_foundation_parse_tests pp_foundation_task_queue_tests pp_foundation_trace_tests pp_assets_brush_package_tests pp_assets_image_format_tests pp_assets_image_metadata_tests pp_assets_image_pixels_tests pp_assets_ppi_header_tests pp_assets_settings_document_tests pp_paint_brush_tests pp_paint_blend_tests pp_paint_stroke_tests pp_paint_stroke_script_tests pp_document_tests pp_document_ppi_import_tests pp_document_ppi_export_tests pp_renderer_api_tests pp_renderer_gl_capabilities_tests pp_renderer_gl_command_plan_tests pp_paint_renderer_compositor_tests pp_platform_api_tests pp_ui_core_color_tests pp_ui_core_layout_value_tests pp_ui_core_layout_xml_tests pp_app_core_about_menu_tests pp_app_core_app_preferences_tests pp_app_core_app_frame_tests pp_app_core_app_thread_tests pp_app_core_app_input_tests pp_app_core_app_shutdown_tests pp_app_core_app_startup_tests pp_app_core_app_status_tests pp_app_core_command_convert_tests pp_app_core_brush_package_export_tests pp_app_core_brush_package_import_tests pp_app_core_brush_ui_tests pp_app_core_canvas_hotkey_tests pp_app_core_canvas_tool_ui_tests pp_app_core_canvas_view_tests pp_app_core_document_animation_tests pp_app_core_document_canvas_tests pp_app_core_document_cloud_tests pp_app_core_document_export_tests pp_app_core_document_import_tests pp_app_core_document_layer_tests pp_app_core_document_platform_io_tests pp_app_core_document_recording_tests pp_app_core_document_resize_tests pp_app_core_document_route_tests pp_app_core_document_sharing_tests pp_app_core_document_session_tests pp_app_core_file_menu_tests pp_app_core_grid_ui_tests pp_app_core_history_ui_tests pp_app_core_main_toolbar_tests pp_app_core_quick_ui_tests pp_app_core_tools_menu_tests}"
start="$(date +%s)"
android_cmake_cmd=""
case " $presets " in
*" android-"*)
# shellcheck disable=SC1091
. "$(dirname "$0")/android-sdk-env.sh"
set_android_sdk_toolchain_environment || exit 1
android_cmake_cmd="$ANDROID_CMAKE_COMMAND"
;;
esac
overall_exit=0
results=""
first_result=1
@@ -17,14 +27,21 @@ done
normalized_presets="$(printf '%s' "$presets" | tr ',' ' ')"
for preset in $normalized_presets; do
cmake --preset "$preset"
cmake_cmd="cmake"
case "$preset" in
android-*)
cmake_cmd="$android_cmake_cmd"
;;
esac
"$cmake_cmd" --preset "$preset"
configure_exit="$?"
if [ "$configure_exit" -ne 0 ]; then
[ "$overall_exit" -eq 0 ] && overall_exit="$configure_exit"
result="$(printf '{"preset":"%s","stage":"configure","exitCode":%s}' "$preset" "$configure_exit")"
else
# shellcheck disable=SC2086
cmake --build --preset "$preset" $build_args
"$cmake_cmd" --build --preset "$preset" $build_args
build_exit="$?"
[ "$build_exit" -ne 0 ] && [ "$overall_exit" -eq 0 ] && overall_exit="$build_exit"
result="$(printf '{"preset":"%s","stage":"build","targets":"%s","exitCode":%s}' "$preset" "$targets" "$build_exit")"
@@ -40,5 +57,9 @@ done
end="$(date +%s)"
elapsed_ms="$(( (end - start) * 1000 ))"
printf '{"command":"platform-build","exitCode":%s,"elapsedMs":%s,"results":[%s]}\n' "$overall_exit" "$elapsed_ms" "$results"
if [ -n "${ANDROID_NDK_HOME:-}" ] && [ -n "${ANDROID_CMAKE_COMMAND:-}" ]; then
printf '{"command":"platform-build","exitCode":%s,"elapsedMs":%s,"androidToolchain":{"sdkRoot":"%s","ndkVersion":"%s","ndkPath":"%s","cmakeVersion":"%s","cmakeCommand":"%s"},"results":[%s]}\n' "$overall_exit" "$elapsed_ms" "$ANDROID_SDK_ROOT" "$ANDROID_NDK_VERSION" "$ANDROID_NDK_HOME" "$ANDROID_CMAKE_VERSION" "$ANDROID_CMAKE_COMMAND" "$results"
else
printf '{"command":"platform-build","exitCode":%s,"elapsedMs":%s,"results":[%s]}\n' "$overall_exit" "$elapsed_ms" "$results"
fi
exit "$overall_exit"