# .\build.ps1 [name] [version] # 手动编译脚本,与 GoReleaser 配置保持一致 $binName = $args[0] if (-Not $binName) { $binName = 'hostsync' # 项目默认名称 } # version by args or git tag $version = $args[1] if (-Not $version) { try { $version = git describe --tags --abbrev=0 2>&1 | Where-Object { $_.GetType().Name -eq 'String' } # only use version number \d+\.\d+\.\d+ format if ($version -match 'v(\d+\.\d+\.\d+)') { $version = "$($matches[1])" } else { $version = $null # 如果没有匹配到版本号,则设置为 null } } catch { $version = $null } } # use short commit hash if no tag if (-Not $version) { $version = "$(git rev-parse --short HEAD)" } Write-Host "Building $binName $version" -ForegroundColor Green # output dir $outputDir = "dist-${version}" Remove-Item -Recurse -Force $outputDir -ErrorAction SilentlyContinue | Out-Null New-Item -ItemType Directory -Path $outputDir -ErrorAction Stop | Out-Null # check if upx is available $upxAvailable = $false try { $null = Get-Command upx -ErrorAction Stop $upxAvailable = $true Write-Host 'UPX detected, will compress binaries after build' } catch { Write-Host 'UPX not found, binaries will not be compressed' } # 与 GoReleaser 配置完全一致的平台组合 $targets = @( # Darwin (macOS) - 忽略 386 和 arm @{ GOOS = 'darwin'; GOARCH = 'amd64'; GOARM = ''; EXT = ''; Name = 'darwin-amd64' }, @{ GOOS = 'darwin'; GOARCH = 'arm64'; GOARM = ''; EXT = ''; Name = 'darwin-arm64' }, # Linux - 支持所有架构 @{ GOOS = 'linux'; GOARCH = '386'; GOARM = ''; EXT = ''; Name = 'linux-386' }, @{ GOOS = 'linux'; GOARCH = 'amd64'; GOARM = ''; EXT = ''; Name = 'linux-amd64' }, @{ GOOS = 'linux'; GOARCH = 'arm'; GOARM = '6'; EXT = ''; Name = 'linux-armv6' }, @{ GOOS = 'linux'; GOARCH = 'arm'; GOARM = '7'; EXT = ''; Name = 'linux-armv7' }, @{ GOOS = 'linux'; GOARCH = 'arm64'; GOARM = ''; EXT = ''; Name = 'linux-arm64' }, # Windows - 忽略 arm (32位) @{ GOOS = 'windows'; GOARCH = '386'; GOARM = ''; EXT = '.exe'; Name = 'windows-386' }, @{ GOOS = 'windows'; GOARCH = 'amd64'; GOARM = ''; EXT = '.exe'; Name = 'windows-amd64' }, @{ GOOS = 'windows'; GOARCH = 'arm64'; GOARM = ''; EXT = '.exe'; Name = 'windows-arm64' } ) foreach ($target in $targets) { $index = $targets.IndexOf($target) $total = $targets.Count $prg = '{0:P0}' -f ($index / $total) # 构建符合 GoReleaser 规范的文件名 $output = "$outputDir\$binName-$version-$($target.Name)$($target.EXT)" $time = Get-Date -Format 'yyyy-MM-dd HH:mm:ss' Write-Host -NoNewline ("`r[$prg] Building $output ...").PadRight($host.ui.rawui.windowsize.width / 2, ' ')$time # 设置环境变量 $env:GOOS = $target.GOOS $env:GOARCH = $target.GOARCH if ($target.GOARM) { $env:GOARM = $target.GOARM } else { $env:GOARM = '' } # 构建 try { $commitHash = git rev-parse --short HEAD 2>&1 | Where-Object { $_.GetType().Name -eq 'String' } } catch { $commitHash = 'unknown' } $ldflags = "-s -w -X main.version=$version -X main.commit=$commitHash -X main.date=$(Get-Date -Format 'yyyy-MM-ddTHH:mm:ssZ') -X main.builtBy=manual" go build -ldflags="$ldflags" -trimpath -o $output # compress with upx if available if ($upxAvailable) { $time = Get-Date -Format 'yyyy-MM-dd HH:mm:ss' Write-Host -NoNewline ("`r[$prg] Compressing $output ...").PadRight($host.ui.rawui.windowsize.width / 2, ' ')$time upx --best --lzma -q $output | Out-Null } } $time = Get-Date -Format 'yyyy-MM-dd HH:mm:ss' Write-Host -NoNewline ("`r[100%] All done.").padright($host.ui.rawui.windowsize.width / 2, ' ')$time # reset env $env:GOOS = $env:GOARCH = $env:GOARM = '' # 生成校验和文件,文件名与 GoReleaser 一致 Write-Host "`n📋 Generating checksums..." -ForegroundColor Yellow $checksumFile = "$outputDir\SHA256SUMS" $hash = Get-FileHash -Algorithm SHA256 -Path $outputDir\* | Where-Object { $_.Path -notlike '*SHA256SUMS' } $hash | ForEach-Object { $filename = Split-Path $_.Path -Leaf $_.Hash.ToLower() + ' ' + $filename } | Out-File -FilePath $checksumFile -Encoding utf8 Write-Host "✅ Build completed. Files generated in $outputDir" -ForegroundColor Green Write-Host "📁 Total files: $($hash.Count + 1) (including checksum)" -ForegroundColor Cyan