Install latest Android SDK toolchain packages

This commit is contained in:
2026-06-05 13:12:30 +02:00
parent e731c06330
commit 8a4ca331cb
7 changed files with 313 additions and 29 deletions

View File

@@ -105,10 +105,10 @@ Known local toolchain state:
this host; the wrapper falls back to bundled Visual Studio vcpkg roots when this host; the wrapper falls back to bundled Visual Studio vcpkg roots when
needed. needed.
- Android SDK: `C:\Users\omara\AppData\Local\Android\Sdk` - Android SDK: `C:\Users\omara\AppData\Local\Android\Sdk`
- Android NDK: latest SDK Manager package selected by - Android NDK: latest SDK Manager package checked/installed/selected by
`scripts/automation/android-sdk-env.ps1`; currently `scripts/automation/android-sdk-env.ps1`; currently
`C:\Users\omara\AppData\Local\Android\Sdk\ndk\30.0.14904198` `C:\Users\omara\AppData\Local\Android\Sdk\ndk\30.0.14904198`
- Android CMake: latest SDK Manager package selected by - Android CMake: latest SDK Manager package checked/installed/selected by
`scripts/automation/android-sdk-env.ps1`; currently `scripts/automation/android-sdk-env.ps1`; currently
`C:\Users\omara\AppData\Local\Android\Sdk\cmake\4.1.2` `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 - clang-cl: `C:\Program Files\LLVM\bin\clang-cl.exe` reports 18.1.8, but the
@@ -181,7 +181,8 @@ powershell -ExecutionPolicy Bypass -File scripts\automation\apple-remote-build.p
and shell wrapper defaults include every current CMake test executable plus and shell wrapper defaults include every current CMake test executable plus
the required component and `pano_cli` targets, and that both wrappers default the required component and `pano_cli` targets, and that both wrappers default
to the standard arm64/x64, Quest arm64, and Focus/Wave arm64 Android presets. to the standard arm64/x64, Quest arm64, and Focus/Wave arm64 Android presets.
It also guards the root CMake platform automation target names. It also guards the root CMake platform automation target names and the
PowerShell/shell Android SDK Manager update hooks.
- `package-smoke.ps1 -ReadinessOnly` and `package-smoke.sh --readiness-only` - `package-smoke.ps1 -ReadinessOnly` and `package-smoke.sh --readiness-only`
emit the Windows AppX, Android standard/Quest/Focus APK, Apple bundle, and emit the Windows AppX, Android standard/Quest/Focus APK, Apple bundle, and
WebGL package readiness matrix without first building an app artifact. The WebGL package readiness matrix without first building an app artifact. The

View File

@@ -256,12 +256,14 @@ agent or engineer to remove them without reconstructing context from chat.
The standard arm64 `native-lib` package target builds and links directly; The standard arm64 `native-lib` package target builds and links directly;
Quest and Focus package CMake paths configure with the current Yoga source Quest and Focus package CMake paths configure with the current Yoga source
list. APK/package migration into root CMake remains open. list. APK/package migration into root CMake remains open.
- 2026-06-05: DEBT-0009 was narrowed again. Android automation now selects the - 2026-06-05: DEBT-0009 was narrowed again. Android automation now queries
newest installed SDK Manager NDK/CMake pair through `sdkmanager` for the newest available NDK/CMake packages, installs newer or
`scripts/automation/android-sdk-env.*`, reports that toolchain in structured missing versions when needed, selects the resulting pair through
wrapper output, and the current host installed/validated NDK `30.0.14904198` `scripts/automation/android-sdk-env.*`, and reports package update decisions
plus CMake `4.1.2`. Root Android `pp_assets`, retained standard in structured wrapper output. The current host reports NDK `30.0.14904198`
`native-lib`, and retained Quest/Focus configure gates pass with that pair. and CMake `4.1.2` as `already-latest-available`; root Android `pp_assets`,
retained standard `native-lib`, and retained Quest/Focus configure gates pass
with that pair.
- 2026-06-05: DEBT-0011 was narrowed again. `package-smoke.ps1` now has - 2026-06-05: DEBT-0011 was narrowed again. `package-smoke.ps1` now has
`-AndroidNativeChecks`, which invokes the retained Android standard `-AndroidNativeChecks`, which invokes the retained Android standard
`native-lib` build and Quest/Focus configure helper for selected Android `native-lib` build and Quest/Focus configure helper for selected Android
@@ -314,7 +316,7 @@ 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-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, and root CMake now exposes a focused `panopainter_platform_build_vcpkg_ui_core` target for the vcpkg-backed `pp_ui_core`/tinyxml2 boundary, 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 | `cmake --preset windows-msvc-vcpkg-headless`; `ctest --preset desktop-fast-vcpkg --build-config Debug`; `cmake --build --preset windows-msvc-default --config Debug --target panopainter_platform_build_vcpkg_ui_core` | Component targets consume vcpkg packages where reliable and desktop app, Android, and Apple triplets are validated or explicitly documented as permanent vendor exceptions | | DEBT-0007 | Open | Modernization | `vcpkg.json` and `windows-msvc-vcpkg-headless` are validated for the headless Windows component matrix, and root CMake now exposes a focused `panopainter_platform_build_vcpkg_ui_core` target for the vcpkg-backed `pp_ui_core`/tinyxml2 boundary, 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 | `cmake --preset windows-msvc-vcpkg-headless`; `ctest --preset desktop-fast-vcpkg --build-config Debug`; `cmake --build --preset windows-msvc-default --config Debug --target panopainter_platform_build_vcpkg_ui_core` | 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-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; root CMake exposes non-default platform-build and 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`; `cmake --build --preset windows-msvc-default --config Debug --target panopainter_platform_build_android_assets`; `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-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 queries `sdkmanager`, installs newer or missing SDK Manager NDK/CMake packages, selects the resulting pair before configure, and reports update decisions; root CMake exposes non-default platform-build and 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`; `cmake --build --preset windows-msvc-default --config Debug --target panopainter_platform_build_android_assets`; `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-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; the Windows app smoke and retained Android package native CMake paths are reachable from root CMake package validation targets, but Windows AppX/APK/Apple/WebGL package 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`; `cmake --build --preset windows-msvc-default --config Debug --target panopainter_windows_app_package_smoke`; `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-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; the Windows app smoke and retained Android package native CMake paths are reachable from root CMake package validation targets, but Windows AppX/APK/Apple/WebGL package 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`; `cmake --build --preset windows-msvc-default --config Debug --target panopainter_windows_app_package_smoke`; `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-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 |

View File

@@ -1437,11 +1437,12 @@ monolithically, and share a generated `nanort` compatibility overlay from
`android/cmake/PanoPainterAndroidLegacyCompat.cmake` instead of dirtying the `android/cmake/PanoPainterAndroidLegacyCompat.cmake` instead of dirtying the
vendor submodule. The standard package `native-lib` arm64 target now compiles 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 and links with the current NDK; Quest and Focus configure with the aligned Yoga
source list and their SDK imported-library paths. Android automation now source list and their SDK imported-library paths. Android automation now uses
discovers the newest installed SDK-managed NDK and CMake package before `sdkmanager` to compare the newest available SDK-managed NDK and CMake packages,
configuring Android presets or retained package paths; on the current Windows installs newer or missing packages when needed, and selects those versions
host that selects NDK `30.0.14904198` and CMake `4.1.2` after installing the before configuring Android presets or retained package paths; on the current
latest NDK through `sdkmanager`. Windows host both NDK `30.0.14904198` and CMake `4.1.2` report
`already-latest-available`.
Implementation tasks: Implementation tasks:
@@ -2395,9 +2396,10 @@ Results:
configures/builds `native-lib` directly for arm64 using C++23 and the shared configures/builds `native-lib` directly for arm64 using C++23 and the shared
modern component source set, while Quest and Focus package CMake paths modern component source set, while Quest and Focus package CMake paths
configure with the same compatibility helper and current Yoga source list. configure with the same compatibility helper and current Yoga source list.
The Android platform-build wrapper and retained package helper now select the The Android platform-build wrapper and retained package helper now query
newest installed SDK Manager NDK/CMake pair automatically and report the `sdkmanager`, install newer/missing SDK Manager NDK/CMake packages when
selected versions in their structured output. `package-smoke.ps1 needed, select that pair automatically, and report the selected versions plus
update decisions in their structured output. `package-smoke.ps1
-ReadinessOnly -AndroidNativeChecks -PackageKinds -ReadinessOnly -AndroidNativeChecks -PackageKinds
android-standard-apk,android-quest-apk,android-focus-apk` now runs those android-standard-apk,android-quest-apk,android-focus-apk` now runs those
retained native checks from the package-smoke surface while keeping APK retained native checks from the package-smoke surface while keeping APK

View File

@@ -41,10 +41,154 @@ function Get-LatestAndroidSdkPackageDirectory {
return $packages[0] return $packages[0]
} }
function Get-AndroidSdkManagerCommand {
param([Parameter(Mandatory=$true)][string]$SdkRoot)
$candidates = @(
(Join-Path $SdkRoot "cmdline-tools\latest\bin\sdkmanager.bat"),
(Join-Path $SdkRoot "cmdline-tools\latest\bin\sdkmanager.exe"),
(Join-Path $SdkRoot "tools\bin\sdkmanager.bat"),
(Join-Path $SdkRoot "tools\bin\sdkmanager.exe")
)
$cmdlineToolsRoot = Join-Path $SdkRoot "cmdline-tools"
if (Test-Path -LiteralPath $cmdlineToolsRoot -PathType Container) {
$toolVersions = @(Get-ChildItem -LiteralPath $cmdlineToolsRoot -Directory |
Where-Object { $_.Name -ne "latest" } |
Sort-Object {
try { [version]$_.Name } catch { [version]"0.0" }
} -Descending)
foreach ($toolVersion in $toolVersions) {
$candidates += (Join-Path $toolVersion.FullName "bin\sdkmanager.bat")
$candidates += (Join-Path $toolVersion.FullName "bin\sdkmanager.exe")
}
}
foreach ($candidate in $candidates) {
if ($candidate -and (Test-Path -LiteralPath $candidate -PathType Leaf)) {
return (Resolve-Path -LiteralPath $candidate).Path
}
}
$pathCommand = Get-Command "sdkmanager" -ErrorAction SilentlyContinue
if ($pathCommand) {
return $pathCommand.Source
}
return $null
}
function Get-LatestAvailableAndroidSdkPackageVersion {
param(
[Parameter(Mandatory=$true)][string]$SdkRoot,
[Parameter(Mandatory=$true)][string]$SdkManagerCommand,
[Parameter(Mandatory=$true)][string]$PackageName
)
$output = @(& $SdkManagerCommand "--sdk_root=$SdkRoot" "--list" 2>&1)
$exitCode = $LASTEXITCODE
if ($exitCode -ne 0) {
throw "sdkmanager --list failed while checking $PackageName packages: $($output -join [Environment]::NewLine)"
}
$versions = @()
$pattern = "^\s*$([regex]::Escape($PackageName));([0-9]+(?:\.[0-9]+)*)\s*\|"
foreach ($line in $output) {
$text = $line.ToString()
if ($text -match $pattern) {
$versions += $Matches[1]
}
}
if ($versions.Count -eq 0) {
return $null
}
return @($versions | Sort-Object { [version]$_ } -Descending | Select-Object -First 1)[0]
}
function Install-AndroidSdkPackage {
param(
[Parameter(Mandatory=$true)][string]$SdkRoot,
[Parameter(Mandatory=$true)][string]$SdkManagerCommand,
[Parameter(Mandatory=$true)][string]$PackageId
)
$licenseInput = ("y`n" * 100)
$output = @($licenseInput | & $SdkManagerCommand "--sdk_root=$SdkRoot" "--install" $PackageId 2>&1)
$exitCode = $LASTEXITCODE
if ($exitCode -ne 0) {
throw "sdkmanager failed to install $PackageId with exit code ${exitCode}: $($output -join [Environment]::NewLine)"
}
}
function Ensure-LatestAndroidSdkPackageDirectory {
param(
[Parameter(Mandatory=$true)][string]$SdkRoot,
[Parameter(Mandatory=$true)][string]$PackageName,
[string]$SdkManagerCommand
)
$installedBefore = $null
try {
$installedBefore = Get-LatestAndroidSdkPackageDirectory -SdkRoot $SdkRoot -PackageName $PackageName
} catch {
$installedBefore = $null
}
$availableVersion = $null
$action = "using-installed"
if ($SdkManagerCommand) {
$availableVersion = Get-LatestAvailableAndroidSdkPackageVersion `
-SdkRoot $SdkRoot `
-SdkManagerCommand $SdkManagerCommand `
-PackageName $PackageName
$installedVersion = if ($installedBefore) { [version]$installedBefore.Name } else { $null }
$availableParsed = if ($availableVersion) { [version]$availableVersion } else { $null }
if ($availableParsed -and (!$installedVersion -or $availableParsed -gt $installedVersion)) {
Install-AndroidSdkPackage `
-SdkRoot $SdkRoot `
-SdkManagerCommand $SdkManagerCommand `
-PackageId "$PackageName;$availableVersion"
$action = "installed-latest-available"
} elseif ($availableParsed) {
$action = "already-latest-available"
} else {
$action = "available-version-not-listed"
}
} elseif (!$installedBefore) {
throw "No installed Android SDK package versions found under $(Join-Path $SdkRoot $PackageName), and sdkmanager was not found."
}
$selected = Get-LatestAndroidSdkPackageDirectory -SdkRoot $SdkRoot -PackageName $PackageName
return [ordered]@{
directory = $selected
update = [ordered]@{
package = $PackageName
installedVersionBefore = if ($installedBefore) { $installedBefore.Name } else { $null }
availableVersion = $availableVersion
selectedVersion = $selected.Name
action = $action
}
}
}
function Set-AndroidSdkToolchainEnvironment { function Set-AndroidSdkToolchainEnvironment {
$sdkRoot = Get-AndroidSdkRoot $sdkRoot = Get-AndroidSdkRoot
$ndk = Get-LatestAndroidSdkPackageDirectory -SdkRoot $sdkRoot -PackageName "ndk" $sdkManagerCommand = Get-AndroidSdkManagerCommand -SdkRoot $sdkRoot
$cmake = Get-LatestAndroidSdkPackageDirectory -SdkRoot $sdkRoot -PackageName "cmake" $ndkSelection = Ensure-LatestAndroidSdkPackageDirectory `
-SdkRoot $sdkRoot `
-PackageName "ndk" `
-SdkManagerCommand $sdkManagerCommand
$cmakeSelection = Ensure-LatestAndroidSdkPackageDirectory `
-SdkRoot $sdkRoot `
-PackageName "cmake" `
-SdkManagerCommand $sdkManagerCommand
$ndk = $ndkSelection.directory
$cmake = $cmakeSelection.directory
$cmakeCommand = Join-Path $cmake.FullName "bin\cmake.exe" $cmakeCommand = Join-Path $cmake.FullName "bin\cmake.exe"
if (!(Test-Path -LiteralPath $cmakeCommand -PathType Leaf)) { if (!(Test-Path -LiteralPath $cmakeCommand -PathType Leaf)) {
@@ -58,6 +202,8 @@ function Set-AndroidSdkToolchainEnvironment {
return [ordered]@{ return [ordered]@{
sdkRoot = $sdkRoot sdkRoot = $sdkRoot
sdkManagerCommand = $sdkManagerCommand
packageUpdates = @($ndkSelection.update, $cmakeSelection.update)
ndkVersion = $ndk.Name ndkVersion = $ndk.Name
ndkPath = $ndk.FullName ndkPath = $ndk.FullName
cmakeVersion = $cmake.Name cmakeVersion = $cmake.Name

View File

@@ -46,21 +46,143 @@ latest_android_package_dir() {
printf '%s/%s\n' "$package_root" "$latest" printf '%s/%s\n' "$package_root" "$latest"
} }
android_sdkmanager_command() {
root="$1"
for candidate in \
"$root/cmdline-tools/latest/bin/sdkmanager" \
"$root/cmdline-tools/latest/bin/sdkmanager.bat" \
"$root/tools/bin/sdkmanager" \
"$root/tools/bin/sdkmanager.bat"
do
if [ -x "$candidate" ] || [ -f "$candidate" ]; then
printf '%s\n' "$candidate"
return 0
fi
done
if [ -d "$root/cmdline-tools" ]; then
for version in "$root/cmdline-tools"/*; do
[ -d "$version" ] || continue
[ "${version##*/}" = "latest" ] && continue
for candidate in "$version/bin/sdkmanager" "$version/bin/sdkmanager.bat"; do
if [ -x "$candidate" ] || [ -f "$candidate" ]; then
printf '%s\n' "$candidate"
return 0
fi
done
done
fi
if command -v sdkmanager >/dev/null 2>&1; then
command -v sdkmanager
return 0
fi
return 1
}
latest_version_from_stdin() {
sort -t . -k 1,1n -k 2,2n -k 3,3n -k 4,4n -k 5,5n | tail -n 1
}
latest_available_android_package_version() {
root="$1"
sdkmanager_cmd="$2"
package="$3"
output="$("$sdkmanager_cmd" "--sdk_root=$root" --list)" || return 1
printf '%s\n' "$output" |
sed -n "s/^[[:space:]]*$package;\\([0-9][0-9.]*\\)[[:space:]]*|.*/\\1/p" |
latest_version_from_stdin
}
accept_android_sdk_licenses() {
i=0
while [ "$i" -lt 100 ]; do
printf '%s\n' "y"
i="$((i + 1))"
done
}
install_android_sdk_package() {
root="$1"
sdkmanager_cmd="$2"
package_id="$3"
accept_android_sdk_licenses | "$sdkmanager_cmd" "--sdk_root=$root" --install "$package_id" >&2
}
record_android_package_update() {
package="$1"
installed_before="$2"
available="$3"
selected="$4"
action="$5"
case "$package" in
ndk)
ANDROID_NDK_INSTALLED_BEFORE="$installed_before"
ANDROID_NDK_AVAILABLE_VERSION="$available"
ANDROID_NDK_UPDATE_ACTION="$action"
;;
cmake)
ANDROID_CMAKE_INSTALLED_BEFORE="$installed_before"
ANDROID_CMAKE_AVAILABLE_VERSION="$available"
ANDROID_CMAKE_UPDATE_ACTION="$action"
;;
esac
export ANDROID_NDK_INSTALLED_BEFORE ANDROID_NDK_AVAILABLE_VERSION ANDROID_NDK_UPDATE_ACTION
export ANDROID_CMAKE_INSTALLED_BEFORE ANDROID_CMAKE_AVAILABLE_VERSION ANDROID_CMAKE_UPDATE_ACTION
printf '%s\n' "$selected" >/dev/null
}
ensure_latest_android_package_dir() {
root="$1"
package="$2"
sdkmanager_cmd="${3:-}"
installed_dir="$(latest_android_package_dir "$root" "$package" 2>/dev/null || true)"
installed_before="${installed_dir##*/}"
[ -n "$installed_dir" ] || installed_before=""
available_version=""
action="using-installed"
if [ -n "$sdkmanager_cmd" ]; then
available_version="$(latest_available_android_package_version "$root" "$sdkmanager_cmd" "$package")" || return 1
if [ -n "$available_version" ]; then
if [ -z "$installed_before" ]; then
install_android_sdk_package "$root" "$sdkmanager_cmd" "$package;$available_version" || return 1
action="installed-latest-available"
else
newest="$(printf '%s\n%s\n' "$installed_before" "$available_version" | latest_version_from_stdin)"
if [ "$newest" = "$available_version" ] && [ "$available_version" != "$installed_before" ]; then
install_android_sdk_package "$root" "$sdkmanager_cmd" "$package;$available_version" || return 1
action="installed-latest-available"
else
action="already-latest-available"
fi
fi
else
action="available-version-not-listed"
fi
elif [ -z "$installed_dir" ]; then
printf '%s\n' "No installed Android SDK package was found under $root/$package, and sdkmanager was not found." >&2
return 1
fi
selected_dir="$(latest_android_package_dir "$root" "$package")" || return 1
record_android_package_update "$package" "$installed_before" "$available_version" "${selected_dir##*/}" "$action"
printf '%s\n' "$selected_dir"
}
set_android_sdk_toolchain_environment() { set_android_sdk_toolchain_environment() {
sdk_root="$(android_sdk_root)" || { sdk_root="$(android_sdk_root)" || {
printf '%s\n' "Android SDK root was not found. Install command-line tools or set ANDROID_SDK_ROOT." >&2 printf '%s\n' "Android SDK root was not found. Install command-line tools or set ANDROID_SDK_ROOT." >&2
return 1 return 1
} }
ndk_dir="$(latest_android_package_dir "$sdk_root" ndk)" || { sdkmanager_cmd="$(android_sdkmanager_command "$sdk_root" || true)"
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)" || { ndk_dir="$(ensure_latest_android_package_dir "$sdk_root" ndk "$sdkmanager_cmd")" || return 1
printf '%s\n' "No installed Android CMake package was found under $sdk_root/cmake." >&2 cmake_dir="$(ensure_latest_android_package_dir "$sdk_root" cmake "$sdkmanager_cmd")" || return 1
return 1
}
cmake_command="$cmake_dir/bin/cmake" cmake_command="$cmake_dir/bin/cmake"
[ -x "$cmake_command" ] || { [ -x "$cmake_command" ] || {
@@ -75,4 +197,5 @@ set_android_sdk_toolchain_environment() {
export ANDROID_CMAKE_COMMAND="$cmake_command" export ANDROID_CMAKE_COMMAND="$cmake_command"
export ANDROID_NDK_VERSION="${ndk_dir##*/}" export ANDROID_NDK_VERSION="${ndk_dir##*/}"
export ANDROID_CMAKE_VERSION="${cmake_dir##*/}" export ANDROID_CMAKE_VERSION="${cmake_dir##*/}"
export ANDROID_SDKMANAGER_COMMAND="$sdkmanager_cmd"
} }

View File

@@ -58,7 +58,7 @@ done
end="$(date +%s)" end="$(date +%s)"
elapsed_ms="$(( (end - start) * 1000 ))" elapsed_ms="$(( (end - start) * 1000 ))"
if [ -n "${ANDROID_NDK_HOME:-}" ] && [ -n "${ANDROID_CMAKE_COMMAND:-}" ]; then 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" printf '{"command":"platform-build","exitCode":%s,"elapsedMs":%s,"androidToolchain":{"sdkRoot":"%s","sdkManagerCommand":"%s","packageUpdates":[{"package":"ndk","installedVersionBefore":"%s","availableVersion":"%s","selectedVersion":"%s","action":"%s"},{"package":"cmake","installedVersionBefore":"%s","availableVersion":"%s","selectedVersion":"%s","action":"%s"}],"ndkVersion":"%s","ndkPath":"%s","cmakeVersion":"%s","cmakeCommand":"%s"},"results":[%s]}\n' "$overall_exit" "$elapsed_ms" "$ANDROID_SDK_ROOT" "$ANDROID_SDKMANAGER_COMMAND" "$ANDROID_NDK_INSTALLED_BEFORE" "$ANDROID_NDK_AVAILABLE_VERSION" "$ANDROID_NDK_VERSION" "$ANDROID_NDK_UPDATE_ACTION" "$ANDROID_CMAKE_INSTALLED_BEFORE" "$ANDROID_CMAKE_AVAILABLE_VERSION" "$ANDROID_CMAKE_VERSION" "$ANDROID_CMAKE_UPDATE_ACTION" "$ANDROID_NDK_VERSION" "$ANDROID_NDK_HOME" "$ANDROID_CMAKE_VERSION" "$ANDROID_CMAKE_COMMAND" "$results"
else else
printf '{"command":"platform-build","exitCode":%s,"elapsedMs":%s,"results":[%s]}\n' "$overall_exit" "$elapsed_ms" "$results" printf '{"command":"platform-build","exitCode":%s,"elapsedMs":%s,"results":[%s]}\n' "$overall_exit" "$elapsed_ms" "$results"
fi fi

View File

@@ -109,6 +109,14 @@ def main() -> int:
target: target in cmake_platform_module for target in EXPECTED_CMAKE_PLATFORM_TARGETS target: target in cmake_platform_module for target in EXPECTED_CMAKE_PLATFORM_TARGETS
} }
cmake_platform_module_included = "include(PanoPainterPlatformTargets)" in root_cmake cmake_platform_module_included = "include(PanoPainterPlatformTargets)" in root_cmake
android_sdk_env = {
"android-sdk-env.ps1": (root / "scripts" / "automation" / "android-sdk-env.ps1").read_text(encoding="utf-8"),
"android-sdk-env.sh": (root / "scripts" / "automation" / "android-sdk-env.sh").read_text(encoding="utf-8"),
}
android_sdkmanager_update_support = {
name: all(token in text for token in ("sdkmanager", "--list", "--install", "ndk", "cmake"))
for name, text in android_sdk_env.items()
}
result = { result = {
"ok": True, "ok": True,
@@ -122,6 +130,7 @@ def main() -> int:
}, },
"cmakePlatformTargetsPresent": cmake_platform_targets_present, "cmakePlatformTargetsPresent": cmake_platform_targets_present,
"cmakePlatformModuleIncluded": cmake_platform_module_included, "cmakePlatformModuleIncluded": cmake_platform_module_included,
"androidSdkmanagerUpdateSupport": android_sdkmanager_update_support,
"missing": { "missing": {
"platform-build.ps1.targets": missing(expected, ps_targets), "platform-build.ps1.targets": missing(expected, ps_targets),
"platform-build.sh.targets": missing(expected, sh_targets), "platform-build.sh.targets": missing(expected, sh_targets),
@@ -133,6 +142,7 @@ def main() -> int:
all(not values for values in result["missing"].values()) all(not values for values in result["missing"].values())
and all(cmake_platform_targets_present.values()) and all(cmake_platform_targets_present.values())
and cmake_platform_module_included and cmake_platform_module_included
and all(android_sdkmanager_update_support.values())
) )
print(json.dumps(result, separators=(",", ":"))) print(json.dumps(result, separators=(",", ":")))