From 8a4ca331cbf89093514d30ef29f74f23d9ad0fe0 Mon Sep 17 00:00:00 2001 From: omigamedev Date: Fri, 5 Jun 2026 13:12:30 +0200 Subject: [PATCH] Install latest Android SDK toolchain packages --- docs/modernization/build-inventory.md | 7 +- docs/modernization/debt.md | 16 ++- docs/modernization/roadmap.md | 18 +-- scripts/automation/android-sdk-env.ps1 | 150 +++++++++++++++++++- scripts/automation/android-sdk-env.sh | 139 ++++++++++++++++-- scripts/automation/platform-build.sh | 2 +- scripts/dev/check_platform_build_targets.py | 10 ++ 7 files changed, 313 insertions(+), 29 deletions(-) diff --git a/docs/modernization/build-inventory.md b/docs/modernization/build-inventory.md index 12b9df1..2da46d8 100644 --- a/docs/modernization/build-inventory.md +++ b/docs/modernization/build-inventory.md @@ -105,10 +105,10 @@ Known local toolchain state: this host; the wrapper falls back to bundled Visual Studio vcpkg roots when needed. - 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 `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 `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 @@ -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 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. - 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` emit the Windows AppX, Android standard/Quest/Focus APK, Apple bundle, and WebGL package readiness matrix without first building an app artifact. The diff --git a/docs/modernization/debt.md b/docs/modernization/debt.md index acb2286..2458938 100644 --- a/docs/modernization/debt.md +++ b/docs/modernization/debt.md @@ -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; 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-05: DEBT-0009 was narrowed again. Android automation now queries + `sdkmanager` for the newest available NDK/CMake packages, installs newer or + missing versions when needed, selects the resulting pair through + `scripts/automation/android-sdk-env.*`, and reports package update decisions + in structured wrapper output. The current host reports NDK `30.0.14904198` + 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 `-AndroidNativeChecks`, which invokes the retained Android standard `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-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-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-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 | diff --git a/docs/modernization/roadmap.md b/docs/modernization/roadmap.md index c1f9d2f..b7f25e5 100644 --- a/docs/modernization/roadmap.md +++ b/docs/modernization/roadmap.md @@ -1437,11 +1437,12 @@ 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. 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`. +source list and their SDK imported-library paths. Android automation now uses +`sdkmanager` to compare the newest available SDK-managed NDK and CMake packages, +installs newer or missing packages when needed, and selects those versions +before configuring Android presets or retained package paths; on the current +Windows host both NDK `30.0.14904198` and CMake `4.1.2` report +`already-latest-available`. Implementation tasks: @@ -2395,9 +2396,10 @@ 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. `package-smoke.ps1 + The Android platform-build wrapper and retained package helper now query + `sdkmanager`, install newer/missing SDK Manager NDK/CMake packages when + needed, select that pair automatically, and report the selected versions plus + update decisions in their structured output. `package-smoke.ps1 -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 diff --git a/scripts/automation/android-sdk-env.ps1 b/scripts/automation/android-sdk-env.ps1 index 060e163..3d4d579 100644 --- a/scripts/automation/android-sdk-env.ps1 +++ b/scripts/automation/android-sdk-env.ps1 @@ -41,10 +41,154 @@ function Get-LatestAndroidSdkPackageDirectory { 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 { $sdkRoot = Get-AndroidSdkRoot - $ndk = Get-LatestAndroidSdkPackageDirectory -SdkRoot $sdkRoot -PackageName "ndk" - $cmake = Get-LatestAndroidSdkPackageDirectory -SdkRoot $sdkRoot -PackageName "cmake" + $sdkManagerCommand = Get-AndroidSdkManagerCommand -SdkRoot $sdkRoot + $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" if (!(Test-Path -LiteralPath $cmakeCommand -PathType Leaf)) { @@ -58,6 +202,8 @@ function Set-AndroidSdkToolchainEnvironment { return [ordered]@{ sdkRoot = $sdkRoot + sdkManagerCommand = $sdkManagerCommand + packageUpdates = @($ndkSelection.update, $cmakeSelection.update) ndkVersion = $ndk.Name ndkPath = $ndk.FullName cmakeVersion = $cmake.Name diff --git a/scripts/automation/android-sdk-env.sh b/scripts/automation/android-sdk-env.sh index 5e076ce..35d3477 100644 --- a/scripts/automation/android-sdk-env.sh +++ b/scripts/automation/android-sdk-env.sh @@ -46,21 +46,143 @@ latest_android_package_dir() { 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() { 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 - } + sdkmanager_cmd="$(android_sdkmanager_command "$sdk_root" || true)" - 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 - } + ndk_dir="$(ensure_latest_android_package_dir "$sdk_root" ndk "$sdkmanager_cmd")" || return 1 + cmake_dir="$(ensure_latest_android_package_dir "$sdk_root" cmake "$sdkmanager_cmd")" || return 1 cmake_command="$cmake_dir/bin/cmake" [ -x "$cmake_command" ] || { @@ -75,4 +197,5 @@ set_android_sdk_toolchain_environment() { export ANDROID_CMAKE_COMMAND="$cmake_command" export ANDROID_NDK_VERSION="${ndk_dir##*/}" export ANDROID_CMAKE_VERSION="${cmake_dir##*/}" + export ANDROID_SDKMANAGER_COMMAND="$sdkmanager_cmd" } diff --git a/scripts/automation/platform-build.sh b/scripts/automation/platform-build.sh index b8ad928..905d8eb 100644 --- a/scripts/automation/platform-build.sh +++ b/scripts/automation/platform-build.sh @@ -58,7 +58,7 @@ done end="$(date +%s)" elapsed_ms="$(( (end - start) * 1000 ))" 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 printf '{"command":"platform-build","exitCode":%s,"elapsedMs":%s,"results":[%s]}\n' "$overall_exit" "$elapsed_ms" "$results" fi diff --git a/scripts/dev/check_platform_build_targets.py b/scripts/dev/check_platform_build_targets.py index 9ce236b..9b06777 100644 --- a/scripts/dev/check_platform_build_targets.py +++ b/scripts/dev/check_platform_build_targets.py @@ -109,6 +109,14 @@ def main() -> int: target: target in cmake_platform_module for target in EXPECTED_CMAKE_PLATFORM_TARGETS } 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 = { "ok": True, @@ -122,6 +130,7 @@ def main() -> int: }, "cmakePlatformTargetsPresent": cmake_platform_targets_present, "cmakePlatformModuleIncluded": cmake_platform_module_included, + "androidSdkmanagerUpdateSupport": android_sdkmanager_update_support, "missing": { "platform-build.ps1.targets": missing(expected, ps_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()) and all(cmake_platform_targets_present.values()) and cmake_platform_module_included + and all(android_sdkmanager_update_support.values()) ) print(json.dumps(result, separators=(",", ":")))