# GoTunnel Build Script for Windows # Usage: .\build.ps1 [command] # Commands: all, current, web, server, client, android, clean, help param( [Parameter(Position=0)] [string]$Command = "all", [string]$Version = "dev", [switch]$NoUPX ) $ErrorActionPreference = "Stop" $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).ToUniversalTime().ToString("yyyy-MM-dd HH:mm:ss") try { $GitCommit = (git -C $RootDir rev-parse --short HEAD 2>$null) if (-not $GitCommit) { $GitCommit = "unknown" } } catch { $GitCommit = "unknown" } $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 Write-Host $Message } function Write-Warn { param([string]$Message) Write-Host "[WARN] " -ForegroundColor Yellow -NoNewline Write-Host $Message } function Write-Err { param([string]$Message) Write-Host "[ERROR] " -ForegroundColor Red -NoNewline Write-Host $Message } function Test-UPX { try { $null = Get-Command upx -ErrorAction Stop return $true } catch { return $false } } function Compress-Binary { param( [string]$FilePath, [string]$OS ) if ($NoUPX) { return } if (-not (Test-UPX)) { Write-Warn "UPX not found, skipping compression" return } if ($OS -eq "darwin") { Write-Warn "Skipping UPX for macOS binary: $FilePath" return } Write-Info "Compressing $FilePath with UPX..." try { & upx -9 -q $FilePath 2>$null } catch { Write-Warn "UPX compression failed for $FilePath" } } function Build-Web { Write-Info "Building web UI..." $WebDir = Join-Path $RootDir "web" Push-Location $WebDir try { if (-not (Test-Path "node_modules")) { Write-Info "Installing npm dependencies..." & npm install if ($LASTEXITCODE -ne 0) { throw "npm install failed" } } & npm run build if ($LASTEXITCODE -ne 0) { throw "npm build failed" } } finally { Pop-Location } Write-Info "Copying dist to embed directory..." $DistSource = Join-Path $WebDir "dist" $DistDest = Join-Path $RootDir "internal\server\app\dist" if (Test-Path $DistDest) { Remove-Item -Recurse -Force $DistDest } Copy-Item -Recurse $DistSource $DistDest 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 ) $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 '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" } Compress-Binary -FilePath $OutputPath -OS $OS $FileSize = (Get-Item $OutputPath).Length / 1MB Write-Info (" -> {0} ({1:N2} MB)" -f $OutputPath, $FileSize) } function Build-All { foreach ($Platform in $DesktopPlatforms) { Build-Binary -OS $Platform.OS -Arch $Platform.Arch -Component "server" Build-Binary -OS $Platform.OS -Arch $Platform.Arch -Component "client" } Write-Info "" Write-Info "Build completed! Output directory: $BuildDir" Write-Info "" Write-Info "Built files:" Get-ChildItem -Recurse $BuildDir -File | ForEach-Object { $RelPath = $_.FullName.Replace($BuildDir, "").TrimStart("\") $Size = "{0:N2} MB" -f ($_.Length / 1MB) Write-Host " $RelPath ($Size)" } } function Build-Current { $OS = go env GOOS $Arch = go env GOARCH Build-Binary -OS $OS -Arch $Arch -Component "server" Build-Binary -OS $OS -Arch $Arch -Component "client" 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) { Remove-Item -Recurse -Force $BuildDir } Write-Info "Clean completed" } function Show-Help { Write-Host @" GoTunnel Build Script for Windows Usage: .\build.ps1 [command] [-Version ] [-NoUPX] 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 Options: -Version Set version string (default: dev) -NoUPX Disable UPX compression Target platforms: - windows/amd64 - linux/amd64 - linux/arm64 - darwin/amd64 - darwin/arm64 Examples: .\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 try { Write-Info "GoTunnel Build Script" Write-Info "Version: $Version | Commit: $GitCommit" Write-Info "" switch ($Command.ToLower()) { "all" { Build-Web Build-All } "current" { Build-Web Build-Current } "web" { Build-Web } "server" { $OS = go env GOOS $Arch = go env GOARCH Build-Binary -OS $OS -Arch $Arch -Component "server" } "client" { $OS = go env GOOS $Arch = go env GOARCH Build-Binary -OS $OS -Arch $Arch -Component "client" } "android" { Build-Android } "clean" { Clean-Build } { $_ -in @("help", "--help", "-h", "/?") } { Show-Help return } default { Write-Err "Unknown command: $Command" Show-Help exit 1 } } Write-Info "" Write-Info "Done!" } finally { Pop-Location } } Main