<# .SYNOPSIS Build libzstd.a and libsign.a for Android (4 ABIs) .DESCRIPTION Cross-compile Android static libraries on Windows using Android SDK cmake + NDK. Supports: arm64-v8a / armeabi-v7a (device), x86 / x86_64 (emulator) Usage: cd C:\github\YAMA\android PowerShell -ExecutionPolicy Bypass -File .\build_android_libs.ps1 Options: -Force Rebuild even if .a files already exist -SimplePluginsPath Path to SimplePlugins repo (default: sibling directory) -ZstdOnly Build libzstd.a only -SignOnly Build libsign.a only #> param( [switch]$Force, [string]$SimplePluginsPath = "", [switch]$ZstdOnly, [switch]$SignOnly ) Set-StrictMode -Version Latest $ErrorActionPreference = "Stop" $SCRIPT_DIR = $PSScriptRoot # -- Android SDK --------------------------------------------------------------- $SDK = $env:ANDROID_HOME if (-not $SDK) { $SDK = $env:ANDROID_SDK_ROOT } if (-not $SDK) { $SDK = "$env:LOCALAPPDATA\Android\Sdk" } if (-not (Test-Path $SDK)) { Write-Error "Android SDK not found: $SDK`nSet ANDROID_HOME environment variable." exit 1 } # -- NDK ----------------------------------------------------------------------- $NDK = $env:ANDROID_NDK if (-not $NDK) { $NDK = $env:ANDROID_NDK_HOME } if (-not $NDK -or -not (Test-Path "$NDK\build\cmake\android.toolchain.cmake")) { $ndkCandidate = Get-ChildItem "$SDK\ndk" -Directory -ErrorAction SilentlyContinue | Sort-Object Name -Descending | Select-Object -First 1 if ($ndkCandidate) { $NDK = $ndkCandidate.FullName } } if (-not (Test-Path "$NDK\build\cmake\android.toolchain.cmake")) { Write-Error "NDK not found. Install via Android Studio > SDK Manager > NDK, or set ANDROID_NDK." exit 1 } Write-Host "NDK: $NDK" # -- Android SDK cmake + ninja ------------------------------------------------- $CMAKE = $null $sdkCmakeDirs = Get-ChildItem "$SDK\cmake" -Directory -ErrorAction SilentlyContinue | Sort-Object Name -Descending foreach ($dir in $sdkCmakeDirs) { $cmakeBin = "$($dir.FullName)\bin\cmake.exe" $ninjaBin = "$($dir.FullName)\bin\ninja.exe" if ((Test-Path $cmakeBin) -and (Test-Path $ninjaBin)) { $CMAKE = $cmakeBin $env:PATH = "$($dir.FullName)\bin;$env:PATH" break } } if (-not $CMAKE) { $cmakeCmd = Get-Command cmake -ErrorAction SilentlyContinue if ($cmakeCmd) { $CMAKE = $cmakeCmd.Source } } if (-not $CMAKE) { Write-Error "cmake not found. Install via Android Studio > SDK Manager > cmake." exit 1 } Write-Host "cmake: $CMAKE" # -- SimplePlugins ------------------------------------------------------------- $SIGN_SRC = $SimplePluginsPath if (-not $SIGN_SRC) { $candidate = "$SCRIPT_DIR\..\..\SimplePlugins" if (Test-Path $candidate) { $SIGN_SRC = (Resolve-Path $candidate).Path } } if ((-not $ZstdOnly) -and (-not (Test-Path "$SIGN_SRC\license_unix.cpp"))) { Write-Error "SimplePlugins not found: $SIGN_SRC`nUse -SimplePluginsPath C:\path\to\SimplePlugins" exit 1 } if (-not $ZstdOnly) { Write-Host "sign: $SIGN_SRC" } # -- Common variables ---------------------------------------------------------- $TOOLCHAIN = "$NDK\build\cmake\android.toolchain.cmake" $ABIS = @("arm64-v8a", "armeabi-v7a", "x86", "x86_64") $LIB_BASE = "$SCRIPT_DIR\app\src\main\cpp\lib" # ============================================================================== # Part 1 - libzstd.a # ============================================================================== if (-not $SignOnly) { $ZSTD_VER = "1.5.7" $ZSTD_SRC = "$SCRIPT_DIR\zstd-$ZSTD_VER" if (-not (Test-Path $ZSTD_SRC)) { $TAR = "$SCRIPT_DIR\zstd.tar.gz" Write-Host "`nDownloading zstd $ZSTD_VER..." Invoke-WebRequest ` "https://github.com/facebook/zstd/releases/download/v$ZSTD_VER/zstd-$ZSTD_VER.tar.gz" ` -OutFile $TAR Write-Host "Extracting..." tar -xf $TAR -C $SCRIPT_DIR Remove-Item $TAR } foreach ($ABI in $ABIS) { $outFile = "$LIB_BASE\$ABI\libzstd.a" if ((Test-Path $outFile) -and (-not $Force)) { Write-Host "`n[skip] zstd $ABI -- already exists (use -Force to rebuild)" continue } Write-Host "`n===== zstd $ABI =====" $BUILD = "$SCRIPT_DIR\zstd_build\$ABI" Remove-Item -Recurse -Force $BUILD -ErrorAction SilentlyContinue New-Item -ItemType Directory -Force "$LIB_BASE\$ABI" | Out-Null $configArgs = @( "-B", $BUILD, "-S", "$ZSTD_SRC\build\cmake", "-G", "Ninja", "-DCMAKE_TOOLCHAIN_FILE=$TOOLCHAIN", "-DANDROID_ABI=$ABI", "-DANDROID_PLATFORM=android-21", "-DCMAKE_BUILD_TYPE=Release", "-DCMAKE_C_FLAGS=-O2 -g0", "-DZSTD_BUILD_STATIC=ON", "-DZSTD_BUILD_SHARED=OFF", "-DZSTD_BUILD_PROGRAMS=OFF", "-DZSTD_BUILD_TESTS=OFF", "-DZSTD_LEGACY_SUPPORT=0" ) & $CMAKE @configArgs if ($LASTEXITCODE -ne 0) { Write-Error "cmake configure failed"; exit 1 } & $CMAKE --build $BUILD --config Release if ($LASTEXITCODE -ne 0) { Write-Error "cmake build failed"; exit 1 } Copy-Item "$BUILD\lib\libzstd.a" $outFile -Force $sz = [math]::Round((Get-Item $outFile).Length / 1KB) Write-Host " --> $outFile (${sz} KB)" } Remove-Item -Recurse -Force "$SCRIPT_DIR\zstd_build" -ErrorAction SilentlyContinue Remove-Item -Recurse -Force $ZSTD_SRC -ErrorAction SilentlyContinue } # ============================================================================== # Part 2 - libsign.a # ============================================================================== if (-not $ZstdOnly) { foreach ($ABI in $ABIS) { $outFile = "$LIB_BASE\$ABI\libsign.a" if ((Test-Path $outFile) -and (-not $Force)) { Write-Host "`n[skip] sign $ABI -- already exists (use -Force to rebuild)" continue } Write-Host "`n===== sign $ABI =====" $BUILD = "$SCRIPT_DIR\sign_build\$ABI" Remove-Item -Recurse -Force $BUILD -ErrorAction SilentlyContinue New-Item -ItemType Directory -Force "$LIB_BASE\$ABI" | Out-Null $configArgs = @( "-B", $BUILD, "-S", "$SIGN_SRC\sign_lib", "-G", "Ninja", "-DCMAKE_TOOLCHAIN_FILE=$TOOLCHAIN", "-DANDROID_ABI=$ABI", "-DANDROID_PLATFORM=android-21", "-DCMAKE_BUILD_TYPE=Release", "-DCMAKE_C_FLAGS=-Os -g0" ) & $CMAKE @configArgs if ($LASTEXITCODE -ne 0) { Write-Error "cmake configure failed"; exit 1 } & $CMAKE --build $BUILD --config Release if ($LASTEXITCODE -ne 0) { Write-Error "cmake build failed"; exit 1 } Copy-Item "$BUILD\libsign.a" $outFile -Force $sz = [math]::Round((Get-Item $outFile).Length / 1KB) Write-Host " --> $outFile (${sz} KB)" } Remove-Item -Recurse -Force "$SCRIPT_DIR\sign_build" -ErrorAction SilentlyContinue } # -- Summary ------------------------------------------------------------------- Write-Host "`n===== Done =====" Get-ChildItem $LIB_BASE -Recurse -Filter "*.a" | Sort-Object FullName | ForEach-Object { $rel = $_.FullName.Substring($LIB_BASE.Length + 1) $sz = [math]::Round($_.Length / 1KB) Write-Host (" {0,-40} {1,6} KB" -f $rel, $sz) }