Files
frpc-console/script/build.go
T

202 lines
4.3 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
//go:build ignore
// build.go
package main
import (
"bufio"
"fmt"
"os"
"os/exec"
"path/filepath"
"strings"
)
type Platform struct {
OS string
Arch string
Name string // 显示名称
Ext string // 文件扩展名(Windows 需要 .exe
}
var platforms = []Platform{
{"windows", "amd64", "Windows x86-64", ".exe"},
{"windows", "386", "Windows x86", ".exe"},
{"linux", "amd64", "Linux x86-64", ""},
{"linux", "arm64", "Linux ARM64", ""},
{"linux", "armv7", "Linux ARMv7", ""},
}
const (
Version = "1.0.0"
BuildTime = "2026-07-24"
Binary = "frpc-console"
)
func main() {
// 解析命令行参数
if len(os.Args) > 1 {
target := os.Args[1]
if target == "all" {
buildAll()
return
}
if target == "clean" {
clean()
return
}
if target == "list" {
listPlatforms()
return
}
// 尝试匹配平台
for _, p := range platforms {
if target == p.OS+"/"+p.Arch {
build(p, false)
return
}
}
fmt.Println("❌ 不支持的平台:", target)
fmt.Println(" 可用: windows/amd64, windows/386, linux/amd64, linux/arm64, linux/armv7")
fmt.Println(" 或: all, list, clean")
return
}
// 交互式菜单
interactiveMenu()
}
func listPlatforms() {
fmt.Println("可用平台:")
for i, p := range platforms {
fmt.Printf(" %d. %s (%s/%s)\n", i+1, p.Name, p.OS, p.Arch)
}
}
func interactiveMenu() {
fmt.Println("========================================")
fmt.Println(" frpc-console 多平台构建工具 v" + Version)
fmt.Println("========================================")
fmt.Println()
for i, p := range platforms {
fmt.Printf(" %d. %s (%s/%s)\n", i+1, p.Name, p.OS, p.Arch)
}
fmt.Println(" a. 全部构建")
fmt.Println(" c. 清理构建产物")
fmt.Println(" q. 退出")
fmt.Println()
reader := bufio.NewReader(os.Stdin)
fmt.Print("请选择: ")
input, _ := reader.ReadString('\n')
input = strings.TrimSpace(strings.ToLower(input))
switch input {
case "q":
fmt.Println("已退出")
return
case "c":
clean()
return
case "a":
buildAll()
return
default:
// 尝试匹配数字
var idx int
if n, err := fmt.Sscanf(input, "%d", &idx); n == 1 && err == nil && idx >= 1 && idx <= len(platforms) {
build(platforms[idx-1], false)
return
}
fmt.Println("❌ 无效选择")
interactiveMenu()
}
}
func buildAll() {
for _, p := range platforms {
build(p, true)
}
fmt.Println("\n✅ 全部构建完成!产物位于 build/ 目录")
}
func build(p Platform, silent bool) {
if !silent {
fmt.Printf("🔨 构建 %s (%s/%s)...\n", p.Name, p.OS, p.Arch)
}
outDir := "./build"
if err := os.MkdirAll(outDir, 0755); err != nil {
fmt.Printf("❌ 创建目录失败: %v\n", err)
return
}
outName := Binary + "-" + p.OS + "-" + p.Arch + p.Ext
outPath := filepath.Join(outDir, outName)
// 构建命令
cmd := exec.Command("go.exe", "build",
"-ldflags=-s -w -X main.version="+Version,
"-o", outPath,
".",
)
cmd.Env = append(os.Environ(),
"GOOS="+p.OS,
"GOARCH="+p.Arch,
"CGO_ENABLED=0", // 禁用 CGO,保证静态编译
)
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
if err := cmd.Run(); err != nil {
fmt.Printf("❌ 构建失败: %v\n", err)
return
}
if !silent {
fmt.Printf("✅ 构建完成: %s\n", outPath)
// 显示文件大小
if info, err := os.Stat(outPath); err == nil {
size := float64(info.Size()) / 1024 / 1024
fmt.Printf(" 📦 %.2f MB\n", size)
}
}
// 打包(仅单平台构建时自动打包)
if !silent {
packageBinary(outPath, p)
}
}
func packageBinary(binPath string, p Platform) {
base := strings.TrimSuffix(filepath.Base(binPath), p.Ext)
dir := filepath.Dir(binPath)
if p.Ext == ".exe" {
// Windows: zip
zipName := filepath.Join(dir, base+".zip")
cmd := exec.Command("zip", "-j", zipName, binPath)
if err := cmd.Run(); err == nil {
fmt.Printf(" 📦 已打包: %s\n", zipName)
}
} else {
// Linux/macOS: tar.gz
tarName := filepath.Join(dir, base+".tar.gz")
cmd := exec.Command("tar", "-czf", tarName, "-C", dir, filepath.Base(binPath))
if err := cmd.Run(); err == nil {
fmt.Printf(" 📦 已打包: %s\n", tarName)
}
}
}
func clean() {
fmt.Println("🧹 清理构建产物...")
if err := os.RemoveAll("./build"); err != nil {
fmt.Printf("❌ 清理失败: %v\n", err)
return
}
fmt.Println("✅ 清理完成")
}