213 lines
7.2 KiB
PowerShell
213 lines
7.2 KiB
PowerShell
[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 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
|
|
$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)) {
|
|
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
|
|
sdkManagerCommand = $sdkManagerCommand
|
|
packageUpdates = @($ndkSelection.update, $cmakeSelection.update)
|
|
ndkVersion = $ndk.Name
|
|
ndkPath = $ndk.FullName
|
|
cmakeVersion = $cmake.Name
|
|
cmakeCommand = $cmakeCommand
|
|
}
|
|
}
|