155 lines
6.1 KiB
PowerShell
155 lines
6.1 KiB
PowerShell
<#
|
|
.SYNOPSIS
|
|
Windows equivalent of build_core.sh - builds the Go core binaries.
|
|
|
|
.DESCRIPTION
|
|
Builds the Android client for every shipped ABI and the Linux client/servers.
|
|
|
|
arm64-v8a builds with CGO disabled and needs no NDK. The other Android ABIs
|
|
do: `GOOS=android` requires external linking for arm, amd64 and 386, so an
|
|
NDK toolchain is located automatically. If none is found those ABIs are
|
|
skipped with a warning rather than failing the build - the APK is still
|
|
installable on 64-bit ARM, which is the overwhelming majority of devices.
|
|
|
|
.EXAMPLE
|
|
.\build_core.ps1
|
|
.\build_core.ps1 -ClientOnly
|
|
.\build_core.ps1 -Abis arm64-v8a,armeabi-v7a
|
|
#>
|
|
[CmdletBinding()]
|
|
param(
|
|
# Only build the Android client (skip the Linux client and servers).
|
|
[switch]$ClientOnly,
|
|
# Root of the APK's lib directory; per-ABI subdirectories are created here.
|
|
[string]$AndroidLibRoot,
|
|
# Which Android ABIs to build.
|
|
[string[]]$Abis = @('arm64-v8a', 'armeabi-v7a', 'x86_64'),
|
|
# NDK root; auto-detected from the SDK when omitted.
|
|
[string]$NdkRoot,
|
|
# Minimum Android API the native cores are built for.
|
|
[int]$MinApi = 24,
|
|
[string]$GoBin = $(if ($env:GO_BIN) { $env:GO_BIN } else { 'go' })
|
|
)
|
|
|
|
$ErrorActionPreference = 'Stop'
|
|
$Root = $PSScriptRoot
|
|
if (-not $AndroidLibRoot) { $AndroidLibRoot = Join-Path $Root 'android\lib' }
|
|
|
|
function Invoke-Go {
|
|
param([hashtable]$Env, [string[]]$GoArgs)
|
|
$saved = @{}
|
|
foreach ($k in $Env.Keys) {
|
|
$saved[$k] = [Environment]::GetEnvironmentVariable($k)
|
|
[Environment]::SetEnvironmentVariable($k, $Env[$k])
|
|
}
|
|
try {
|
|
& $GoBin @GoArgs
|
|
if ($LASTEXITCODE -ne 0) { throw "go build failed (exit $LASTEXITCODE)" }
|
|
} finally {
|
|
foreach ($k in $saved.Keys) { [Environment]::SetEnvironmentVariable($k, $saved[$k]) }
|
|
}
|
|
}
|
|
|
|
# Locate an NDK llvm toolchain bin directory, newest first.
|
|
function Find-NdkBin {
|
|
param([string]$Explicit)
|
|
$roots = @()
|
|
if ($Explicit) { $roots += $Explicit }
|
|
if ($env:ANDROID_NDK_ROOT) { $roots += $env:ANDROID_NDK_ROOT }
|
|
if ($env:ANDROID_NDK_HOME) { $roots += $env:ANDROID_NDK_HOME }
|
|
foreach ($sdk in $env:ANDROID_SDK_ROOT, $env:ANDROID_HOME, "$env:LOCALAPPDATA\Android\Sdk") {
|
|
if ($sdk -and (Test-Path (Join-Path $sdk 'ndk'))) {
|
|
$roots += (Get-ChildItem (Join-Path $sdk 'ndk') -Directory |
|
|
Sort-Object { try { [version]$_.Name } catch { [version]'0.0.0' } } -Descending |
|
|
ForEach-Object { $_.FullName })
|
|
}
|
|
}
|
|
foreach ($r in $roots) {
|
|
if (-not $r) { continue }
|
|
$bin = Join-Path $r 'toolchains\llvm\prebuilt\windows-x86_64\bin'
|
|
if (Test-Path $bin) { return $bin }
|
|
}
|
|
return $null
|
|
}
|
|
|
|
# ABI -> (GOARCH, GOARM, clang triple prefix)
|
|
$abiSpec = @{
|
|
'arm64-v8a' = @{ arch = 'arm64'; arm = ''; cc = 'aarch64-linux-android' }
|
|
'armeabi-v7a' = @{ arch = 'arm'; arm = '7'; cc = 'armv7a-linux-androideabi' }
|
|
'x86_64' = @{ arch = 'amd64'; arm = ''; cc = 'x86_64-linux-android' }
|
|
'x86' = @{ arch = '386'; arm = ''; cc = 'i686-linux-android' }
|
|
}
|
|
|
|
$go = Get-Command $GoBin -ErrorAction SilentlyContinue
|
|
if (-not $go) { throw "Go compiler not found. Install from https://go.dev/dl/ or set -GoBin." }
|
|
|
|
$ndkBin = Find-NdkBin $NdkRoot
|
|
New-Item -ItemType Directory -Force -Path "$Root\bin" | Out-Null
|
|
Push-Location "$Root\core"
|
|
try {
|
|
$ldflags = '-ldflags=-s -w'
|
|
$built = @()
|
|
|
|
foreach ($abi in $Abis) {
|
|
if (-not $abiSpec.ContainsKey($abi)) { Write-Warning "unknown ABI $abi, skipping"; continue }
|
|
$spec = $abiSpec[$abi]
|
|
$outDir = Join-Path $AndroidLibRoot $abi
|
|
$out = Join-Path $outDir 'libdragontcp_client.so'
|
|
|
|
# arm64 links internally; everything else needs the NDK's clang.
|
|
$env = @{ GOOS = 'android'; GOARCH = $spec.arch }
|
|
if ($spec.arm) { $env['GOARM'] = $spec.arm }
|
|
if ($abi -eq 'arm64-v8a') {
|
|
$env['CGO_ENABLED'] = '0'
|
|
} else {
|
|
if (-not $ndkBin) {
|
|
Write-Warning "[core] $abi skipped: no NDK found (set -NdkRoot or ANDROID_NDK_ROOT)"
|
|
continue
|
|
}
|
|
$cc = Join-Path $ndkBin ("{0}{1}-clang.cmd" -f $spec.cc, $MinApi)
|
|
if (-not (Test-Path $cc)) {
|
|
Write-Warning "[core] $abi skipped: $cc not found"
|
|
continue
|
|
}
|
|
$env['CGO_ENABLED'] = '1'
|
|
$env['CC'] = $cc
|
|
}
|
|
|
|
Write-Host "[core] Android $abi client..." -ForegroundColor Cyan
|
|
New-Item -ItemType Directory -Force -Path $outDir | Out-Null
|
|
Invoke-Go $env @('build', '-trimpath', $ldflags, '-o', $out, './cmd/dragontcp-client')
|
|
$built += $abi
|
|
}
|
|
|
|
if (-not $built) { throw 'No Android ABI was built.' }
|
|
Write-Host "[core] Android ABIs: $($built -join ', ')" -ForegroundColor Green
|
|
|
|
# Remove stale ABI directories so the APK never ships an out-of-date core.
|
|
if (Test-Path $AndroidLibRoot) {
|
|
foreach ($dir in Get-ChildItem $AndroidLibRoot -Directory) {
|
|
if ($built -notcontains $dir.Name) {
|
|
Write-Warning "[core] removing stale $($dir.Name) native library"
|
|
Remove-Item $dir.FullName -Recurse -Force
|
|
}
|
|
}
|
|
}
|
|
|
|
if (-not $ClientOnly) {
|
|
Write-Host '[core] Linux AMD64 client...' -ForegroundColor Cyan
|
|
Invoke-Go @{ CGO_ENABLED = '0'; GOOS = 'linux'; GOARCH = 'amd64' } `
|
|
@('build', '-trimpath', $ldflags, '-o', "$Root\bin\dragontcp-hybrid-client-linux-amd64", './cmd/dragontcp-client')
|
|
|
|
Write-Host '[core] Linux AMD64 server...' -ForegroundColor Cyan
|
|
Invoke-Go @{ CGO_ENABLED = '0'; GOOS = 'linux'; GOARCH = 'amd64' } `
|
|
@('build', '-trimpath', $ldflags, '-o', "$Root\bin\dragontcp-hybrid-server-linux-amd64", './cmd/dragontcp-server')
|
|
|
|
Write-Host '[core] Linux ARM64 server...' -ForegroundColor Cyan
|
|
Invoke-Go @{ CGO_ENABLED = '0'; GOOS = 'linux'; GOARCH = 'arm64' } `
|
|
@('build', '-trimpath', $ldflags, '-o', "$Root\bin\dragontcp-hybrid-server-linux-arm64", './cmd/dragontcp-server')
|
|
}
|
|
} finally {
|
|
Pop-Location
|
|
}
|
|
|
|
Write-Host 'Core build complete.' -ForegroundColor Green
|