调整编译逻辑了,增加自写编译器,限定编译平台为Windows
This commit is contained in:
@@ -10,7 +10,6 @@ import (
|
|||||||
"runtime"
|
"runtime"
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
"syscall"
|
|
||||||
"text/template"
|
"text/template"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -174,7 +173,7 @@ func StartFrpc() error {
|
|||||||
|
|
||||||
cmd := exec.Command(frpcPath, "-c", "./frpc.toml")
|
cmd := exec.Command(frpcPath, "-c", "./frpc.toml")
|
||||||
if runtime.GOOS == "windows" {
|
if runtime.GOOS == "windows" {
|
||||||
cmd.SysProcAttr = &syscall.SysProcAttr{HideWindow: true}
|
setWindowHide(cmd)
|
||||||
}
|
}
|
||||||
if err := cmd.Start(); err != nil {
|
if err := cmd.Start(); err != nil {
|
||||||
return fmt.Errorf("启动 frpc 失败: %w", err)
|
return fmt.Errorf("启动 frpc 失败: %w", err)
|
||||||
|
|||||||
@@ -0,0 +1,16 @@
|
|||||||
|
//go:build windows
|
||||||
|
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"os/exec"
|
||||||
|
"syscall"
|
||||||
|
)
|
||||||
|
|
||||||
|
// setWindowHide 在 Windows 上隐藏 frpc 命令行窗口
|
||||||
|
func setWindowHide(cmd *exec.Cmd) {
|
||||||
|
if cmd.SysProcAttr == nil {
|
||||||
|
cmd.SysProcAttr = &syscall.SysProcAttr{}
|
||||||
|
}
|
||||||
|
cmd.SysProcAttr.HideWindow = true
|
||||||
|
}
|
||||||
@@ -0,0 +1,201 @@
|
|||||||
|
//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("✅ 清理完成")
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user