Add Android client support and unify cross-platform builds
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
# GoTunnel Build Script for Windows
|
||||
# Usage: .\build.ps1 [command]
|
||||
# Commands: all, current, web, server, client, clean, help
|
||||
# Commands: all, current, web, server, client, android, clean, help
|
||||
|
||||
param(
|
||||
[Parameter(Position=0)]
|
||||
@@ -13,15 +13,11 @@ param(
|
||||
|
||||
$ErrorActionPreference = "Stop"
|
||||
|
||||
# 项目根目录
|
||||
$RootDir = Split-Path -Parent (Split-Path -Parent $PSScriptRoot)
|
||||
if (-not $RootDir) {
|
||||
$RootDir = Split-Path -Parent (Split-Path -Parent $MyInvocation.MyCommand.Path)
|
||||
}
|
||||
$RootDir = Split-Path -Parent $PSScriptRoot
|
||||
$BuildDir = Join-Path $RootDir "build"
|
||||
$env:GOCACHE = if ($env:GOCACHE) { $env:GOCACHE } else { Join-Path $BuildDir ".gocache" }
|
||||
|
||||
# 版本信息
|
||||
$BuildTime = (Get-Date -Format "yyyy-MM-dd HH:mm:ss")
|
||||
$BuildTime = (Get-Date).ToUniversalTime().ToString("yyyy-MM-dd HH:mm:ss")
|
||||
try {
|
||||
$GitCommit = (git -C $RootDir rev-parse --short HEAD 2>$null)
|
||||
if (-not $GitCommit) { $GitCommit = "unknown" }
|
||||
@@ -29,17 +25,14 @@ try {
|
||||
$GitCommit = "unknown"
|
||||
}
|
||||
|
||||
# 目标平台
|
||||
$Platforms = @(
|
||||
@{OS="windows"; Arch="amd64"},
|
||||
@{OS="linux"; Arch="amd64"},
|
||||
@{OS="linux"; Arch="arm64"},
|
||||
@{OS="darwin"; Arch="amd64"},
|
||||
@{OS="darwin"; Arch="arm64"}
|
||||
)
|
||||
$DesktopPlatforms = @(
|
||||
@{ OS = "windows"; Arch = "amd64" },
|
||||
@{ OS = "linux"; Arch = "amd64" },
|
||||
@{ OS = "linux"; Arch = "arm64" },
|
||||
@{ OS = "darwin"; Arch = "amd64" },
|
||||
@{ OS = "darwin"; Arch = "arm64" }
|
||||
)
|
||||
|
||||
# 颜色输出函数
|
||||
function Write-Info {
|
||||
param([string]$Message)
|
||||
Write-Host "[INFO] " -ForegroundColor Green -NoNewline
|
||||
@@ -58,7 +51,6 @@ function Write-Err {
|
||||
Write-Host $Message
|
||||
}
|
||||
|
||||
# 检查 UPX 是否可用
|
||||
function Test-UPX {
|
||||
try {
|
||||
$null = Get-Command upx -ErrorAction Stop
|
||||
@@ -68,16 +60,17 @@ function Test-UPX {
|
||||
}
|
||||
}
|
||||
|
||||
# UPX 压缩二进制
|
||||
function Compress-Binary {
|
||||
param([string]$FilePath, [string]$OS)
|
||||
param(
|
||||
[string]$FilePath,
|
||||
[string]$OS
|
||||
)
|
||||
|
||||
if ($NoUPX) { return }
|
||||
if (-not (Test-UPX)) {
|
||||
Write-Warn "UPX not found, skipping compression"
|
||||
return
|
||||
}
|
||||
# macOS 二进制不支持 UPX
|
||||
if ($OS -eq "darwin") {
|
||||
Write-Warn "Skipping UPX for macOS binary: $FilePath"
|
||||
return
|
||||
@@ -91,7 +84,6 @@ function Compress-Binary {
|
||||
}
|
||||
}
|
||||
|
||||
# 构建 Web UI
|
||||
function Build-Web {
|
||||
Write-Info "Building web UI..."
|
||||
|
||||
@@ -111,7 +103,6 @@ function Build-Web {
|
||||
Pop-Location
|
||||
}
|
||||
|
||||
# 复制到 embed 目录
|
||||
Write-Info "Copying dist to embed directory..."
|
||||
$DistSource = Join-Path $WebDir "dist"
|
||||
$DistDest = Join-Path $RootDir "internal\server\app\dist"
|
||||
@@ -124,51 +115,55 @@ function Build-Web {
|
||||
Write-Info "Web UI built successfully"
|
||||
}
|
||||
|
||||
# 构建单个二进制
|
||||
function Get-OutputName {
|
||||
param(
|
||||
[string]$Component,
|
||||
[string]$OS
|
||||
)
|
||||
|
||||
if ($OS -eq "windows") {
|
||||
return "$Component.exe"
|
||||
}
|
||||
|
||||
return $Component
|
||||
}
|
||||
|
||||
function Build-Binary {
|
||||
param(
|
||||
[string]$OS,
|
||||
[string]$Arch,
|
||||
[string]$Component # server 或 client
|
||||
[string]$Component
|
||||
)
|
||||
|
||||
$OutputName = $Component
|
||||
if ($OS -eq "windows") {
|
||||
$OutputName = "$Component.exe"
|
||||
}
|
||||
|
||||
$OutputDir = Join-Path $BuildDir "${OS}_${Arch}"
|
||||
if (-not (Test-Path $OutputDir)) {
|
||||
New-Item -ItemType Directory -Path $OutputDir -Force | Out-Null
|
||||
}
|
||||
|
||||
$OutputName = Get-OutputName -Component $Component -OS $OS
|
||||
$OutputPath = Join-Path $OutputDir $OutputName
|
||||
$SourcePath = Join-Path $RootDir "cmd\$Component"
|
||||
|
||||
Write-Info "Building $Component for $OS/$Arch..."
|
||||
|
||||
$env:GOOS = $OS
|
||||
$env:GOARCH = $Arch
|
||||
$env:CGO_ENABLED = "0"
|
||||
|
||||
$LDFlags = "-s -w -X 'github.com/gotunnel/pkg/version.Version=$Version' -X 'github.com/gotunnel/pkg/version.BuildTime=$BuildTime' -X 'github.com/gotunnel/pkg/version.GitCommit=$GitCommit'"
|
||||
$OutputPath = Join-Path $OutputDir $OutputName
|
||||
$SourcePath = Join-Path $RootDir "cmd\$Component"
|
||||
|
||||
& go build -ldflags $LDFlags -o $OutputPath $SourcePath
|
||||
$LdFlags = "-s -w -X 'main.Version=$Version' -X 'main.BuildTime=$BuildTime' -X 'main.GitCommit=$GitCommit'"
|
||||
& go build -buildvcs=false -trimpath -ldflags $LdFlags -o $OutputPath $SourcePath
|
||||
|
||||
if ($LASTEXITCODE -ne 0) {
|
||||
throw "Build failed for $Component $OS/$Arch"
|
||||
}
|
||||
|
||||
# UPX 压缩
|
||||
Compress-Binary -FilePath $OutputPath -OS $OS
|
||||
|
||||
# 显示文件大小
|
||||
$FileSize = (Get-Item $OutputPath).Length / 1MB
|
||||
Write-Info " -> $OutputPath ({0:N2} MB)" -f $FileSize
|
||||
Write-Info (" -> {0} ({1:N2} MB)" -f $OutputPath, $FileSize)
|
||||
}
|
||||
|
||||
# 构建所有平台
|
||||
function Build-All {
|
||||
foreach ($Platform in $Platforms) {
|
||||
foreach ($Platform in $DesktopPlatforms) {
|
||||
Build-Binary -OS $Platform.OS -Arch $Platform.Arch -Component "server"
|
||||
Build-Binary -OS $Platform.OS -Arch $Platform.Arch -Component "client"
|
||||
}
|
||||
@@ -184,7 +179,6 @@ function Build-All {
|
||||
}
|
||||
}
|
||||
|
||||
# 仅构建当前平台
|
||||
function Build-Current {
|
||||
$OS = go env GOOS
|
||||
$Arch = go env GOARCH
|
||||
@@ -195,7 +189,51 @@ function Build-Current {
|
||||
Write-Info "Binaries built in $BuildDir\${OS}_${Arch}\"
|
||||
}
|
||||
|
||||
# 清理构建产物
|
||||
function Build-Android {
|
||||
$OutputDir = Join-Path $BuildDir "android_arm64"
|
||||
if (-not (Test-Path $OutputDir)) {
|
||||
New-Item -ItemType Directory -Path $OutputDir -Force | Out-Null
|
||||
}
|
||||
|
||||
Write-Info "Building client for android/arm64..."
|
||||
$env:GOOS = "android"
|
||||
$env:GOARCH = "arm64"
|
||||
$env:CGO_ENABLED = "0"
|
||||
|
||||
$OutputPath = Join-Path $OutputDir "client"
|
||||
$LdFlags = "-s -w -X 'main.Version=$Version' -X 'main.BuildTime=$BuildTime' -X 'main.GitCommit=$GitCommit'"
|
||||
& go build -buildvcs=false -trimpath -ldflags $LdFlags -o $OutputPath (Join-Path $RootDir "cmd\client")
|
||||
if ($LASTEXITCODE -ne 0) {
|
||||
throw "Build failed for client android/arm64"
|
||||
}
|
||||
|
||||
if (Get-Command gomobile -ErrorAction SilentlyContinue) {
|
||||
Write-Info "Building gomobile Android binding..."
|
||||
& gomobile bind -target android/arm64 -o (Join-Path $OutputDir "gotunnelmobile.aar") "github.com/gotunnel/mobile/gotunnelmobile"
|
||||
if ($LASTEXITCODE -ne 0) {
|
||||
throw "gomobile bind failed"
|
||||
}
|
||||
} else {
|
||||
Write-Warn "gomobile not found, skipping Android AAR build"
|
||||
}
|
||||
|
||||
$GradleWrapper = Join-Path $RootDir "android\gradlew.bat"
|
||||
if (Test-Path $GradleWrapper) {
|
||||
Write-Info "Building Android debug APK..."
|
||||
Push-Location (Join-Path $RootDir "android")
|
||||
try {
|
||||
& $GradleWrapper assembleDebug
|
||||
if ($LASTEXITCODE -ne 0) {
|
||||
throw "Android APK build failed"
|
||||
}
|
||||
} finally {
|
||||
Pop-Location
|
||||
}
|
||||
} else {
|
||||
Write-Warn "android\\gradlew.bat not found, skipping APK build"
|
||||
}
|
||||
}
|
||||
|
||||
function Clean-Build {
|
||||
Write-Info "Cleaning build directory..."
|
||||
if (Test-Path $BuildDir) {
|
||||
@@ -204,7 +242,6 @@ function Clean-Build {
|
||||
Write-Info "Clean completed"
|
||||
}
|
||||
|
||||
# 显示帮助
|
||||
function Show-Help {
|
||||
Write-Host @"
|
||||
GoTunnel Build Script for Windows
|
||||
@@ -212,11 +249,12 @@ GoTunnel Build Script for Windows
|
||||
Usage: .\build.ps1 [command] [-Version <version>] [-NoUPX]
|
||||
|
||||
Commands:
|
||||
all Build web UI + all platforms (default)
|
||||
all Build web UI + all desktop platforms (default)
|
||||
current Build web UI + current platform only
|
||||
web Build web UI only
|
||||
server Build server for current platform
|
||||
client Build client for current platform
|
||||
android Build android/arm64 client and optional Android artifacts
|
||||
clean Clean build directory
|
||||
help Show this help message
|
||||
|
||||
@@ -228,18 +266,17 @@ Target platforms:
|
||||
- windows/amd64
|
||||
- linux/amd64
|
||||
- linux/arm64
|
||||
- darwin/amd64 (macOS Intel)
|
||||
- darwin/arm64 (macOS Apple Silicon)
|
||||
- darwin/amd64
|
||||
- darwin/arm64
|
||||
|
||||
Examples:
|
||||
.\build.ps1 # Build all platforms
|
||||
.\build.ps1 # Build all desktop platforms
|
||||
.\build.ps1 all -Version 1.0.0 # Build with version
|
||||
.\build.ps1 current # Build current platform only
|
||||
.\build.ps1 clean # Clean build directory
|
||||
"@
|
||||
}
|
||||
|
||||
# 主函数
|
||||
function Main {
|
||||
Push-Location $RootDir
|
||||
|
||||
@@ -270,10 +307,13 @@ function Main {
|
||||
$Arch = go env GOARCH
|
||||
Build-Binary -OS $OS -Arch $Arch -Component "client"
|
||||
}
|
||||
"android" {
|
||||
Build-Android
|
||||
}
|
||||
"clean" {
|
||||
Clean-Build
|
||||
}
|
||||
{ $_ -in "help", "--help", "-h", "/?" } {
|
||||
{ $_ -in @("help", "--help", "-h", "/?") } {
|
||||
Show-Help
|
||||
return
|
||||
}
|
||||
@@ -286,7 +326,6 @@ function Main {
|
||||
|
||||
Write-Info ""
|
||||
Write-Info "Done!"
|
||||
|
||||
} finally {
|
||||
Pop-Location
|
||||
}
|
||||
|
||||
179
scripts/build.sh
179
scripts/build.sh
@@ -1,27 +1,22 @@
|
||||
#!/bin/bash
|
||||
|
||||
set -e
|
||||
set -euo pipefail
|
||||
|
||||
# 项目根目录
|
||||
ROOT_DIR="$(cd "$(dirname "$0")/.." && pwd)"
|
||||
BUILD_DIR="$ROOT_DIR/build"
|
||||
export GOCACHE="${GOCACHE:-$BUILD_DIR/.gocache}"
|
||||
|
||||
# 版本信息
|
||||
VERSION="${VERSION:-dev}"
|
||||
BUILD_TIME=$(date -u '+%Y-%m-%d %H:%M:%S')
|
||||
GIT_COMMIT=$(git -C "$ROOT_DIR" rev-parse --short HEAD 2>/dev/null || echo "unknown")
|
||||
|
||||
# 默认目标平台
|
||||
DEFAULT_PLATFORMS="linux/amd64 linux/arm64 darwin/amd64 darwin/arm64 windows/amd64"
|
||||
|
||||
# 是否启用 UPX 压缩
|
||||
BUILD_TIME="$(date -u '+%Y-%m-%d %H:%M:%S')"
|
||||
GIT_COMMIT="$(git -C "$ROOT_DIR" rev-parse --short HEAD 2>/dev/null || echo unknown)"
|
||||
USE_UPX="${USE_UPX:-true}"
|
||||
|
||||
# 颜色输出
|
||||
DESKTOP_PLATFORMS="linux/amd64 linux/arm64 darwin/amd64 darwin/arm64 windows/amd64"
|
||||
|
||||
RED='\033[0;31m'
|
||||
GREEN='\033[0;32m'
|
||||
YELLOW='\033[1;33m'
|
||||
NC='\033[0m' # No Color
|
||||
NC='\033[0m'
|
||||
|
||||
log_info() {
|
||||
echo -e "${GREEN}[INFO]${NC} $1"
|
||||
@@ -35,17 +30,14 @@ log_error() {
|
||||
echo -e "${RED}[ERROR]${NC} $1"
|
||||
}
|
||||
|
||||
# 检查 UPX 是否可用
|
||||
check_upx() {
|
||||
if command -v upx &> /dev/null; then
|
||||
return 0
|
||||
fi
|
||||
return 1
|
||||
command -v upx >/dev/null 2>&1
|
||||
}
|
||||
|
||||
# UPX 压缩二进制
|
||||
compress_binary() {
|
||||
local file=$1
|
||||
local os=$2
|
||||
|
||||
if [ "$USE_UPX" != "true" ]; then
|
||||
return
|
||||
fi
|
||||
@@ -53,27 +45,27 @@ compress_binary() {
|
||||
log_warn "UPX not found, skipping compression"
|
||||
return
|
||||
fi
|
||||
# macOS 二进制不支持 UPX
|
||||
if [[ "$file" == *"darwin"* ]]; then
|
||||
if [ "$os" = "darwin" ]; then
|
||||
log_warn "Skipping UPX for macOS binary: $file"
|
||||
return
|
||||
fi
|
||||
|
||||
log_info "Compressing $file with UPX..."
|
||||
upx -9 -q "$file" 2>/dev/null || log_warn "UPX compression failed for $file"
|
||||
}
|
||||
|
||||
# 构建 Web UI
|
||||
build_web() {
|
||||
log_info "Building web UI..."
|
||||
cd "$ROOT_DIR/web"
|
||||
pushd "$ROOT_DIR/web" >/dev/null
|
||||
|
||||
if [ ! -d "node_modules" ]; then
|
||||
log_info "Installing npm dependencies..."
|
||||
npm install
|
||||
fi
|
||||
npm run build
|
||||
cd "$ROOT_DIR"
|
||||
|
||||
# 复制到 embed 目录
|
||||
popd >/dev/null
|
||||
|
||||
log_info "Copying dist to embed directory..."
|
||||
rm -rf "$ROOT_DIR/internal/server/app/dist"
|
||||
cp -r "$ROOT_DIR/web/dist" "$ROOT_DIR/internal/server/app/dist"
|
||||
@@ -81,85 +73,127 @@ build_web() {
|
||||
log_info "Web UI built successfully"
|
||||
}
|
||||
|
||||
# 构建单个二进制
|
||||
output_name() {
|
||||
local component=$1
|
||||
local os=$2
|
||||
|
||||
if [ "$os" = "windows" ]; then
|
||||
echo "${component}.exe"
|
||||
else
|
||||
echo "${component}"
|
||||
fi
|
||||
}
|
||||
|
||||
build_binary() {
|
||||
local os=$1
|
||||
local arch=$2
|
||||
local component=$3 # server 或 client
|
||||
|
||||
local output_name="${component}"
|
||||
if [ "$os" = "windows" ]; then
|
||||
output_name="${component}.exe"
|
||||
fi
|
||||
local component=$3
|
||||
|
||||
local output_dir="$BUILD_DIR/${os}_${arch}"
|
||||
mkdir -p "$output_dir"
|
||||
local output_file
|
||||
output_file="$(output_name "$component" "$os")"
|
||||
local output_path="$output_dir/$output_file"
|
||||
|
||||
mkdir -p "$output_dir"
|
||||
log_info "Building $component for $os/$arch..."
|
||||
|
||||
GOOS=$os GOARCH=$arch go build \
|
||||
GOOS="$os" GOARCH="$arch" CGO_ENABLED=0 go build \
|
||||
-buildvcs=false \
|
||||
-trimpath \
|
||||
-ldflags "-s -w -X 'main.Version=$VERSION' -X 'main.BuildTime=$BUILD_TIME' -X 'main.GitCommit=$GIT_COMMIT'" \
|
||||
-o "$output_dir/$output_name" \
|
||||
-o "$output_path" \
|
||||
"$ROOT_DIR/cmd/$component"
|
||||
|
||||
# UPX 压缩
|
||||
compress_binary "$output_dir/$output_name"
|
||||
compress_binary "$output_path" "$os"
|
||||
log_info " -> $output_path"
|
||||
}
|
||||
|
||||
# 构建所有平台
|
||||
build_all() {
|
||||
local platforms="${1:-$DEFAULT_PLATFORMS}"
|
||||
local platforms="${1:-$DESKTOP_PLATFORMS}"
|
||||
local platform os arch
|
||||
|
||||
for platform in $platforms; do
|
||||
local os="${platform%/*}"
|
||||
local arch="${platform#*/}"
|
||||
build_binary "$os" "$arch" "server"
|
||||
build_binary "$os" "$arch" "client"
|
||||
os="${platform%/*}"
|
||||
arch="${platform#*/}"
|
||||
build_binary "$os" "$arch" server
|
||||
build_binary "$os" "$arch" client
|
||||
done
|
||||
}
|
||||
|
||||
# 仅构建当前平台
|
||||
build_current() {
|
||||
local os=$(go env GOOS)
|
||||
local arch=$(go env GOARCH)
|
||||
local os
|
||||
local arch
|
||||
|
||||
build_binary "$os" "$arch" "server"
|
||||
build_binary "$os" "$arch" "client"
|
||||
os="$(go env GOOS)"
|
||||
arch="$(go env GOARCH)"
|
||||
|
||||
build_binary "$os" "$arch" server
|
||||
build_binary "$os" "$arch" client
|
||||
|
||||
log_info "Binaries built in $BUILD_DIR/${os}_${arch}/"
|
||||
}
|
||||
|
||||
# 清理构建产物
|
||||
build_android() {
|
||||
local output_dir="$BUILD_DIR/android_arm64"
|
||||
|
||||
mkdir -p "$output_dir"
|
||||
log_info "Building client for android/arm64..."
|
||||
GOOS=android GOARCH=arm64 CGO_ENABLED=0 go build \
|
||||
-buildvcs=false \
|
||||
-trimpath \
|
||||
-ldflags "-s -w -X 'main.Version=$VERSION' -X 'main.BuildTime=$BUILD_TIME' -X 'main.GitCommit=$GIT_COMMIT'" \
|
||||
-o "$output_dir/client" \
|
||||
"$ROOT_DIR/cmd/client"
|
||||
|
||||
if command -v gomobile >/dev/null 2>&1; then
|
||||
log_info "Building gomobile Android binding..."
|
||||
gomobile bind -target=android/arm64 -o "$output_dir/gotunnelmobile.aar" github.com/gotunnel/mobile/gotunnelmobile
|
||||
else
|
||||
log_warn "gomobile not found, skipping Android AAR build"
|
||||
fi
|
||||
|
||||
if [ -d "$ROOT_DIR/android" ]; then
|
||||
if [ -x "$ROOT_DIR/android/gradlew" ]; then
|
||||
log_info "Building Android debug APK..."
|
||||
(cd "$ROOT_DIR/android" && ./gradlew assembleDebug)
|
||||
else
|
||||
log_warn "android/gradlew not found, skipping APK build"
|
||||
fi
|
||||
else
|
||||
log_warn "Android host project not found, skipping APK build"
|
||||
fi
|
||||
}
|
||||
|
||||
clean() {
|
||||
log_info "Cleaning build directory..."
|
||||
rm -rf "$BUILD_DIR"
|
||||
log_info "Clean completed"
|
||||
}
|
||||
|
||||
# 显示帮助
|
||||
show_help() {
|
||||
echo "Usage: $0 [command] [options]"
|
||||
echo ""
|
||||
echo "Commands:"
|
||||
echo " all Build for all platforms (default: $DEFAULT_PLATFORMS)"
|
||||
echo " current Build for current platform only"
|
||||
echo " web Build web UI only"
|
||||
echo " server Build server for current platform"
|
||||
echo " client Build client for current platform"
|
||||
echo " clean Clean build directory"
|
||||
echo " help Show this help message"
|
||||
echo ""
|
||||
echo "Environment variables:"
|
||||
echo " VERSION Set version string (default: dev)"
|
||||
echo " USE_UPX Enable UPX compression (default: true)"
|
||||
echo ""
|
||||
echo "Examples:"
|
||||
echo " $0 current # Build for current platform"
|
||||
echo " $0 all # Build for all platforms"
|
||||
echo " VERSION=1.0.0 $0 all # Build with version"
|
||||
cat <<'EOF'
|
||||
Usage: build.sh [command] [options]
|
||||
|
||||
Commands:
|
||||
all Build web UI + all desktop platforms (default)
|
||||
current Build web UI + current platform only
|
||||
web Build web UI only
|
||||
server Build server for current platform
|
||||
client Build client for current platform
|
||||
android Build android/arm64 client and optional Android artifacts
|
||||
clean Clean build directory
|
||||
help Show this help message
|
||||
|
||||
Environment variables:
|
||||
VERSION Set version string (default: dev)
|
||||
USE_UPX Enable UPX compression (default: true)
|
||||
|
||||
Examples:
|
||||
./scripts/build.sh current
|
||||
VERSION=1.0.0 ./scripts/build.sh all
|
||||
EOF
|
||||
}
|
||||
|
||||
# 主函数
|
||||
main() {
|
||||
cd "$ROOT_DIR"
|
||||
|
||||
@@ -176,10 +210,13 @@ main() {
|
||||
build_web
|
||||
;;
|
||||
server)
|
||||
build_binary "$(go env GOOS)" "$(go env GOARCH)" "server"
|
||||
build_binary "$(go env GOOS)" "$(go env GOARCH)" server
|
||||
;;
|
||||
client)
|
||||
build_binary "$(go env GOOS)" "$(go env GOARCH)" "client"
|
||||
build_binary "$(go env GOOS)" "$(go env GOARCH)" client
|
||||
;;
|
||||
android)
|
||||
build_android
|
||||
;;
|
||||
clean)
|
||||
clean
|
||||
|
||||
Reference in New Issue
Block a user