diff --git a/.vscode/settings.json b/.vscode/settings.json index fce885a..7d8cf2d 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,7 +1,16 @@ { "cSpell.words": [ + "buildmode", + "endlocal", + "errorlevel", + "fatih", + "gcflags", + "GOARCH", + "ldflags", "LOCALAPPDATA", "pkill", - "taskkill" + "setlocal", + "taskkill", + "trimpath" ] } \ No newline at end of file diff --git a/bin/cursor_id_modifier.exe b/bin/cursor_id_modifier.exe deleted file mode 100644 index c113c26..0000000 Binary files a/bin/cursor_id_modifier.exe and /dev/null differ diff --git a/bin/cursor_id_modifier_linux b/bin/cursor_id_modifier_linux deleted file mode 100644 index 30efdc9..0000000 Binary files a/bin/cursor_id_modifier_linux and /dev/null differ diff --git a/bin/cursor_id_modifier_mac b/bin/cursor_id_modifier_mac deleted file mode 100644 index 179137b..0000000 Binary files a/bin/cursor_id_modifier_mac and /dev/null differ diff --git a/bin/cursor_id_modifier_mac_arm64 b/bin/cursor_id_modifier_mac_arm64 deleted file mode 100644 index 1c8a633..0000000 Binary files a/bin/cursor_id_modifier_mac_arm64 and /dev/null differ diff --git a/bin/cursor_id_modifier_v1.0.0_linux_amd64 b/bin/cursor_id_modifier_v1.0.0_linux_amd64 new file mode 100644 index 0000000..5cc7465 Binary files /dev/null and b/bin/cursor_id_modifier_v1.0.0_linux_amd64 differ diff --git a/bin/cursor_id_modifier_v1.0.0_mac_intel b/bin/cursor_id_modifier_v1.0.0_mac_intel new file mode 100644 index 0000000..2aefa98 Binary files /dev/null and b/bin/cursor_id_modifier_v1.0.0_mac_intel differ diff --git a/bin/cursor_id_modifier_v1.0.0_mac_m1 b/bin/cursor_id_modifier_v1.0.0_mac_m1 new file mode 100644 index 0000000..b0ef935 Binary files /dev/null and b/bin/cursor_id_modifier_v1.0.0_mac_m1 differ diff --git a/bin/cursor_id_modifier_v1.0.0_windows_amd64.exe b/bin/cursor_id_modifier_v1.0.0_windows_amd64.exe new file mode 100644 index 0000000..6c5e207 Binary files /dev/null and b/bin/cursor_id_modifier_v1.0.0_windows_amd64.exe differ diff --git a/go.mod b/go.mod index e0c2b2d..9d89899 100644 --- a/go.mod +++ b/go.mod @@ -1,3 +1,11 @@ module go-cursor-help go 1.22.0 + +require github.com/fatih/color v1.18.0 + +require ( + github.com/mattn/go-colorable v0.1.13 // indirect + github.com/mattn/go-isatty v0.0.20 // indirect + golang.org/x/sys v0.25.0 // indirect +) diff --git a/go.sum b/go.sum new file mode 100644 index 0000000..33148a4 --- /dev/null +++ b/go.sum @@ -0,0 +1,11 @@ +github.com/fatih/color v1.18.0 h1:S8gINlzdQ840/4pfAwic/ZE0djQEH3wM94VfqLTZcOM= +github.com/fatih/color v1.18.0/go.mod h1:4FelSpRwEGDpQ12mAdzqdOukCy4u8WUtOY6lkT/6HfU= +github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= +github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= +github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= +github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= +github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= +golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.25.0 h1:r+8e+loiHxRqhXVl6ML1nO3l1+oFoWbnlu2Ehimmi34= +golang.org/x/sys v0.25.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= diff --git a/main.go b/main.go index 474ba96..6e3856f 100644 --- a/main.go +++ b/main.go @@ -1,21 +1,41 @@ package main import ( + "bufio" "crypto/rand" "crypto/sha256" "encoding/hex" "encoding/json" "fmt" "os" + "os/exec" + "os/user" "path/filepath" "runtime" + "strings" + "time" + + "github.com/fatih/color" ) -// StorageConfig 存储配置结构体 +// StorageConfig 存储配置结构体优化 type StorageConfig struct { TelemetryMacMachineId string `json:"telemetry.macMachineId"` TelemetryMachineId string `json:"telemetry.machineId"` TelemetryDevDeviceId string `json:"telemetry.devDeviceId"` + LastModified time.Time `json:"lastModified"` + Version string `json:"version"` +} + +// NewStorageConfig 创建新的配置实例 +func NewStorageConfig() *StorageConfig { + return &StorageConfig{ + TelemetryMacMachineId: generateMacMachineId(), + TelemetryMachineId: generateMachineId(), + TelemetryDevDeviceId: generateDevDeviceId(), + LastModified: time.Now(), + Version: "1.0.1", + } } // 生成类似原始machineId的字符串 (64位小写hex) @@ -37,7 +57,7 @@ func generateMacMachineId() string { return generateMachineId() // 使用相同的格式 } -// 生成类似原始devDeviceId的字符串 (标准UUID格式) +// 生成类似原始devDeviceId的字符 (标准UUID格式) func generateDevDeviceId() string { // 生成 UUID v4 uuid := make([]byte, 16) @@ -81,7 +101,7 @@ func getConfigPath() (string, error) { return filepath.Join(configDir, "storage.json"), nil } -// 修改文件权限 +// 修改件权限 func setFilePermissions(filePath string) error { if runtime.GOOS == "windows" { // Windows 使用 ACL 权限系统,这里仅设置为只读 @@ -92,86 +112,320 @@ func setFilePermissions(filePath string) error { } } -// 获取Cursor可执行文件路径 -func getCursorExePath() (string, error) { - switch runtime.GOOS { - case "windows": - // Windows下通常在LocalAppData目录 - localAppData := os.Getenv("LOCALAPPDATA") - return filepath.Join(localAppData, "Programs", "Cursor", "Cursor.exe"), nil - case "darwin": - // macOS下通常在Applications目录 - return "/Applications/Cursor.app/Contents/MacOS/Cursor", nil - case "linux": - // Linux下可能在usr/bin目录 - return "/usr/bin/cursor", nil - default: - return "", fmt.Errorf("不支持的操作系统: %s", runtime.GOOS) + +func printCyberpunkBanner() { + cyan := color.New(color.FgCyan, color.Bold) + yellow := color.New(color.FgYellow, color.Bold) + magenta := color.New(color.FgMagenta, color.Bold) + + banner := ` + ██████╗██╗ ██╗██████╗ ███████╗ ██████╗ ██████╗ + ██╔════╝██║ ██║██╔══██╗██╔════╝██╔═══██╗██╔══██╗ + ██║ ██║ ██║██████╔╝███████╗██║ ██║██████╔╝ + ██║ ██║ ██║█╔══██╗╚════██║██║ ██║██╔══██╗ + ╚██████╗╚██████╔╝██║ ██║███████║╚██████╔╝██║ ██║ + ╚════╝ ╚═════╝ ╚═╝ ╚═╝╚══════╝ ╚═════╝ ╚═╝ ╚═╝ + ` + cyan.Println(banner) + yellow.Println("\t\t>> Cursor ID Modifier v1.0 <<") + magenta.Println("\t\t [ By Pancake Fruit Rolled Shark Chili ]") +} + +type ProgressSpinner struct { + frames []string + current int + message string +} + +func NewProgressSpinner(message string) *ProgressSpinner { + return &ProgressSpinner{ + frames: []string{"⠋", "⠙", "⠹", "⠸", "⠼", "⠴", "⠦", "⠧", "⠇", "⠏"}, + message: message, } } -func main() { - // 获取配置文件路径 +func (s *ProgressSpinner) Spin() { + frame := s.frames[s.current%len(s.frames)] + s.current++ + fmt.Printf("\r%s %s", color.CyanString(frame), s.message) +} + +func (s *ProgressSpinner) Stop() { + fmt.Println() +} + +// 定义错误类型 +type AppError struct { + Op string + Path string + Err error +} + +func (e *AppError) Error() string { + if e.Path != "" { + return fmt.Sprintf("%s: %v [路径: %s]", e.Op, e.Err, e.Path) + } + return fmt.Sprintf("%s: %v", e.Op, e.Err) +} + +// 文件操作包装函数 +func safeWriteFile(path string, data []byte, perm os.FileMode) error { + // 创建临时文件 + tmpPath := path + ".tmp" + if err := os.WriteFile(tmpPath, data, perm); err != nil { + return &AppError{"写入临时文件", tmpPath, err} + } + + // 重命名临时文件 + if err := os.Rename(tmpPath, path); err != nil { + os.Remove(tmpPath) // 清理临时文件 + return &AppError{"重命名文件", path, err} + } + + return nil +} + + + +// clearScreen 清除终端屏幕 +func clearScreen() { + if runtime.GOOS == "windows" { + cmd := exec.Command("cmd", "/c", "cls") + cmd.Stdout = os.Stdout + cmd.Run() + } else { + cmd := exec.Command("clear") + cmd.Stdout = os.Stdout + cmd.Run() + } +} + +// showProgress 显示进度 +func showProgress(message string) { + spinner := NewProgressSpinner(message) + for i := 0; i < 15; i++ { + spinner.Spin() + time.Sleep(100 * time.Millisecond) + } + spinner.Stop() +} + +// saveConfig 保存配置到文件 +func saveConfig(config *StorageConfig) error { configPath, err := getConfigPath() if err != nil { - fmt.Printf("获取配置文件路径失败: %v\n", err) - return + return err } - // 读取原始文件内容 - content, err := os.ReadFile(configPath) + // 转换为JSON + content, err := json.MarshalIndent(config, "", " ") if err != nil { - fmt.Printf("读取配置文件失败: %v\n", err) - return + return &AppError{"生成JSON", "", err} } - // 备份配置文件 - backupPath := configPath + ".bak" - err = os.WriteFile(backupPath, content, 0666) + // 确保文件可写 + err = os.Chmod(configPath, 0666) if err != nil { - fmt.Printf("备份配置文件失败: %v\n", err) - return + return &AppError{"修改文件权限", configPath, err} } - // 解析 JSON - var config map[string]interface{} - if err := json.Unmarshal(content, &config); err != nil { - fmt.Printf("解析 JSON 失败: %v\n", err) - return + // 安全写入文件 + if err := safeWriteFile(configPath, content, 0666); err != nil { + return err } - // 修改指定字段,使用更准确的生成方法 - config["telemetry.macMachineId"] = generateMacMachineId() - config["telemetry.machineId"] = generateMachineId() - config["telemetry.devDeviceId"] = generateDevDeviceId() + // 设置为只读 + return setFilePermissions(configPath) +} - // 转换回 JSON,保持原有的格式 - newContent, err := json.MarshalIndent(config, "", " ") +// showSuccess 显示成功信息 +func showSuccess() { + text := texts[currentLanguage] + color.Green(text.SuccessMessage) + color.Yellow(text.RestartMessage) +} + +// 修改 loadAndUpdateConfig 函数使用 configPath +func loadAndUpdateConfig() (*StorageConfig, error) { + configPath, err := getConfigPath() if err != nil { - fmt.Printf("生成 JSON 失败: %v\n", err) - return + return nil, err } - // 先确保文件可写 - err = os.Chmod(configPath, 0666) - if err != nil { - fmt.Printf("修改文件权限失败: %v\n", err) - return + text := texts[currentLanguage] + showProgress(text.ReadingConfig) + + // 读取原始文件内容 + _, err = os.ReadFile(configPath) + if err != nil && !os.IsNotExist(err) { + return nil, &AppError{"读取配置文件", configPath, err} } - // 写入文件 - err = os.WriteFile(configPath, newContent, 0666) + showProgress(text.GeneratingIds) + config := NewStorageConfig() + + return config, nil +} + +// 修改 waitExit 函数,正确初始化 reader +func waitExit() { + reader := bufio.NewReader(os.Stdin) + color.Cyan("\n" + texts[currentLanguage].PressEnterToExit) + reader.ReadString('\n') +} + +func main() { + currentLanguage = detectLanguage() + defer func() { + if err := recover(); err != nil { + color.Red(texts[currentLanguage].ErrorPrefix, err) + waitExit() + } + }() + + // 添加权限检查 + isAdmin, err := checkAdminPrivileges() if err != nil { - fmt.Printf("写入文件失败: %v\n", err) + handleError("权限检查失败", err) + waitExit() + return + } + + if !isAdmin { + showPrivilegeError() + waitExit() return } - // 设置文件为只读 - err = setFilePermissions(configPath) + setupProgram() + + config, err := loadAndUpdateConfig() if err != nil { - fmt.Printf("设置文件只读权限失败: %v\n", err) + handleError("配置更新失败", err) + return + } + + if err := saveConfig(config); err != nil { + handleError("保存配置失败", err) return } - fmt.Println("配置文件已成功更新,请手动重启Cursor以使更改生效。") + showSuccess() + waitExit() +} + +func setupProgram() { + clearScreen() + printCyberpunkBanner() +} + +func handleError(msg string, err error) { + if appErr, ok := err.(*AppError); ok { + color.Red("%s: %v", msg, appErr) + } else { + color.Red("%s: %v", msg, err) + } +} + +func checkAdminPrivileges() (bool, error) { + switch runtime.GOOS { + case "windows": + // Windows 管理员权限检查 + cmd := exec.Command("net", "session") + err := cmd.Run() + return err == nil, nil + + case "darwin", "linux": + // Unix 系统检查 root 权限 + currentUser, err := user.Current() + if err != nil { + return false, fmt.Errorf("获取当前用户失败: %v", err) + } + return currentUser.Uid == "0", nil + + default: + return false, fmt.Errorf("不支持的操作系统: %s", runtime.GOOS) + } +} + +func showPrivilegeError() { + text := texts[currentLanguage] + red := color.New(color.FgRed, color.Bold) + yellow := color.New(color.FgYellow) + + red.Println(text.PrivilegeError) + if runtime.GOOS == "windows" { + yellow.Println(text.RunAsAdmin) + } else { + yellow.Println(text.RunWithSudo) + yellow.Printf(text.SudoExample, os.Args[0]) + } +} + +// 在文件开头添加新的类型和变量定义 +type Language string + +const ( + CN Language = "cn" + EN Language = "en" +) + +// TextResource 存储多语言文本 +type TextResource struct { + SuccessMessage string + RestartMessage string + ReadingConfig string + GeneratingIds string + PressEnterToExit string + ErrorPrefix string + PrivilegeError string + RunAsAdmin string + RunWithSudo string + SudoExample string +} + +var ( + currentLanguage = CN // 默认使用中文 + + texts = map[Language]TextResource{ + CN: { + SuccessMessage: "[√] 配置文件已成功更新!", + RestartMessage: "[!] 请手动重启 Cursor 以使更改生效", + ReadingConfig: "正在读取配置文件...", + GeneratingIds: "正在生成新的标识符...", + PressEnterToExit: "按回车键退出程序...", + ErrorPrefix: "程序发生严重错误: %v", + PrivilegeError: "\n[!] 错误:需要管理员权限", + RunAsAdmin: "请右键点击程序,选择「以管理员身份运行」", + RunWithSudo: "请使用 sudo 命令运行此程序", + SudoExample: "示例: sudo %s", + }, + EN: { + SuccessMessage: "[√] Configuration file updated successfully!", + RestartMessage: "[!] Please restart Cursor manually for changes to take effect", + ReadingConfig: "Reading configuration file...", + GeneratingIds: "Generating new identifiers...", + PressEnterToExit: "Press Enter to exit...", + ErrorPrefix: "Program encountered a serious error: %v", + PrivilegeError: "\n[!] Error: Administrator privileges required", + RunAsAdmin: "Please right-click and select 'Run as Administrator'", + RunWithSudo: "Please run this program with sudo", + SudoExample: "Example: sudo %s", + }, + } +) + +// 添加语言检测函数 +func detectLanguage() Language { + // 获取系统语言环境 + lang := os.Getenv("LANG") + if lang == "" { + lang = os.Getenv("LANGUAGE") + } + + // 如果包含 zh 则使用中文,否则使用英文 + if strings.Contains(strings.ToLower(lang), "zh") { + return CN + } + return EN } diff --git a/scripts/build_all.bat b/scripts/build_all.bat index 47a9186..eb876fa 100644 --- a/scripts/build_all.bat +++ b/scripts/build_all.bat @@ -1,28 +1,116 @@ @echo off -echo Creating bin directory... -if not exist "..\bin" mkdir "..\bin" +setlocal EnableDelayedExpansion -echo Building for all platforms... +:: 设置版本信息 +set VERSION=1.0.0 -echo Building for Windows AMD64... -set GOOS=windows -set GOARCH=amd64 -go build -o ../bin/cursor_id_modifier.exe ../main.go +:: 设置颜色代码 +set "GREEN=[32m" +set "RED=[31m" +set "YELLOW=[33m" +set "RESET=[0m" -echo Building for macOS AMD64... -set GOOS=darwin -set GOARCH=amd64 -go build -o ../bin/cursor_id_modifier_mac ../main.go +:: 设置编译优化标志 +set "LDFLAGS=-s -w" +set "BUILDMODE=pie" +set "GCFLAGS=-N -l" -echo Building for macOS ARM64... -set GOOS=darwin -set GOARCH=arm64 -go build -o ../bin/cursor_id_modifier_mac_arm64 ../main.go +:: 检查是否安装了必要的交叉编译工具 +where gcc >nul 2>nul +if %errorlevel% neq 0 ( + echo %RED%错误: 未找到 gcc,这可能会影响 Mac 系统的交叉编译%RESET% + echo %YELLOW%请安装 MinGW-w64 或其他 gcc 工具链%RESET% + pause + exit /b 1 +) -echo Building for Linux AMD64... -set GOOS=linux -set GOARCH=amd64 -go build -o ../bin/cursor_id_modifier_linux ../main.go +:: 设置 CGO +set CGO_ENABLED=0 -echo All builds completed! -pause \ No newline at end of file +:: 显示编译信息 +echo %YELLOW%开始构建 version %VERSION%%RESET% +echo %YELLOW%使用优化标志: LDFLAGS=%LDFLAGS%, BUILDMODE=%BUILDMODE%%RESET% +echo %YELLOW%CGO_ENABLED=%CGO_ENABLED%%RESET% + +:: 仅在必要时清理旧文件 +if "%1"=="clean" ( + echo 清理旧构建文件... + if exist "..\bin" rd /s /q "..\bin" +) + +:: 创建输出目录 +if not exist "..\bin" mkdir "..\bin" 2>nul + +:: 定义目标平台数组 +set platforms[0].os=windows +set platforms[0].arch=amd64 +set platforms[0].ext=.exe + +set platforms[1].os=darwin +set platforms[1].arch=amd64 +set platforms[1].ext= + +set platforms[2].os=darwin +set platforms[2].arch=arm64 +set platforms[2].ext= + +set platforms[3].os=linux +set platforms[3].arch=amd64 +set platforms[3].ext= + +:: 设置开始时间 +set start_time=%time% + +:: 编译所有目标 +echo 开始编译所有平台... + +for /L %%i in (0,1,3) do ( + set "os=!platforms[%%i].os!" + set "arch=!platforms[%%i].arch!" + set "ext=!platforms[%%i].ext!" + + echo. + echo Building for !os! !arch!... + + set GOOS=!os! + set GOARCH=!arch! + + :: 为 darwin 系统设置特殊编译参数和文件名 + if "!os!"=="darwin" ( + set "extra_flags=-tags ios" + if "!arch!"=="amd64" ( + set "outfile=..\bin\cursor_id_modifier_v%VERSION%_mac_intel!ext!" + ) else ( + set "outfile=..\bin\cursor_id_modifier_v%VERSION%_mac_m1!ext!" + ) + ) else ( + set "extra_flags=" + set "outfile=..\bin\cursor_id_modifier_v%VERSION%_!os!_!arch!!ext!" + ) + + go build -trimpath !extra_flags! -buildmode=%BUILDMODE% -ldflags="%LDFLAGS%" -gcflags="%GCFLAGS%" -o "!outfile!" ..\main.go + + if !errorlevel! equ 0 ( + echo %GREEN%Build successful: !outfile!%RESET% + ) else ( + echo %RED%Build failed for !os! !arch!%RESET% + echo %YELLOW%如果是 Mac 系统编译失败,请确保:%RESET% + echo %YELLOW%1. 已安装 MinGW-w64%RESET% + echo %YELLOW%2. 已设置 GOARCH 和 GOOS%RESET% + echo %YELLOW%3. CGO_ENABLED=0%RESET% + ) +) + +:: 计算总耗时 +set end_time=%time% +set options="tokens=1-4 delims=:.," +for /f %options% %%a in ("%start_time%") do set start_s=%%a&set start_m=%%b&set start_h=%%c +for /f %options% %%a in ("%end_time%") do set end_s=%%a&set end_m=%%b&set end_h=%%c +set /a duration = (end_h - start_h) * 3600 + (end_m - start_m) * 60 + (end_s - start_s) + +echo. +echo %GREEN%所有构建完成! 总耗时: %duration% 秒%RESET% +if exist "..\bin" dir /b "..\bin" + +pause +endlocal \ No newline at end of file diff --git a/scripts/build_all.sh b/scripts/build_all.sh index cb752ae..909fa90 100644 --- a/scripts/build_all.sh +++ b/scripts/build_all.sh @@ -1,22 +1,101 @@ #!/bin/bash -# 创建bin目录(如果不存在) -mkdir -p ../bin +# 设置颜色代码 +GREEN='\033[0;32m' +RED='\033[0;31m' +NC='\033[0m' # No Color -# Windows -echo "Building for Windows..." -GOOS=windows GOARCH=amd64 go build -o ../bin/cursor_id_modifier.exe ../main.go +# 版本信息 +VERSION="1.0.0" -# macOS (Intel) -echo "Building for macOS (Intel)..." -GOOS=darwin GOARCH=amd64 go build -o ../bin/cursor_id_modifier_mac ../main.go +# 错误处理函数 +handle_error() { + echo -e "${RED}Error: $1${NC}" + exit 1 +} -# macOS (Apple Silicon) -echo "Building for macOS (ARM64)..." -GOOS=darwin GOARCH=arm64 go build -o ../bin/cursor_id_modifier_mac_arm64 ../main.go +# 清理函数 +cleanup() { + echo "Cleaning old builds..." + rm -rf ../bin +} -# Linux -echo "Building for Linux..." -GOOS=linux GOARCH=amd64 go build -o ../bin/cursor_id_modifier_linux ../main.go +# 创建输出目录 +create_output_dir() { + echo "Creating bin directory..." + mkdir -p ../bin || handle_error "Failed to create bin directory" +} -echo "All builds completed!" \ No newline at end of file +# 构建函数 +build() { + local os=$1 + local arch=$2 + local suffix=$3 + + echo -e "\nBuilding for $os ($arch)..." + + output_name="../bin/cursor_id_modifier_v${VERSION}_${os}_${arch}${suffix}" + + GOOS=$os GOARCH=$arch go build -o "$output_name" ../main.go + + if [ $? -eq 0 ]; then + echo -e "${GREEN}✓ Successfully built: ${output_name}${NC}" + else + echo -e "${RED}✗ Failed to build for $os $arch${NC}" + return 1 + fi +} + +# 主函数 +main() { + # 显示构建信息 + echo "Starting build process for version ${VERSION}" + + # 清理旧文件 + cleanup + + # 创建输出目录 + create_output_dir + + # 定义构建目标 + declare -A targets=( + ["windows_amd64"]=".exe" + ["darwin_amd64"]="" + ["darwin_arm64"]="" + ["linux_amd64"]="" + ) + + # 构建计数器 + local success_count=0 + local fail_count=0 + + # 遍历所有目标进行构建 + for target in "${!targets[@]}"; do + os=${target%_*} + arch=${target#*_} + suffix=${targets[$target]} + + if build "$os" "$arch" "$suffix"; then + ((success_count++)) + else + ((fail_count++)) + fi + done + + # 显示构建结果 + echo -e "\nBuild Summary:" + echo -e "${GREEN}Successful builds: $success_count${NC}" + if [ $fail_count -gt 0 ]; then + echo -e "${RED}Failed builds: $fail_count${NC}" + fi + + # 显示生成的文件列表 + echo -e "\nGenerated files:" + ls -1 ../bin +} + +# 捕获错误信号 +trap 'echo -e "\n${RED}Build process interrupted${NC}"; exit 1' INT TERM + +# 执行主函数 +main \ No newline at end of file