#!/usr/bin/env bash # ./build.sh [name] [version] # 手动编译脚本,与 GoReleaser 配置保持一致 BIN_NAME=$1 if [ -z "$BIN_NAME" ]; then BIN_NAME="hostsync" # 项目默认名称 fi VERSION=$2 if [ -z "$VERSION" ]; then VERSION=$(git describe --tags --abbrev=0 2>/dev/null) # only use tags that start with 'v' and match semantic versioning # then use the number part as version # e.g. v1.2.3 => 1.2.3 if [[ ! "$VERSION" =~ ^v[0-9]+\.[0-9]+\.[0-9]+$ ]]; then VERSION="" else VERSION="${VERSION#v}" # 去掉 'v' 前缀 fi fi # use short commit hash if no tag if [ -z "$VERSION" ]; then VERSION="$(git rev-parse --short HEAD)" fi echo "Building $BIN_NAME $VERSION" OUTPUT_DIR="dist-$VERSION" # output dir rm -rf "$OUTPUT_DIR" >/dev/null 2>&1 mkdir -p "$OUTPUT_DIR" >/dev/null 2>&1 # check if upx is available UPX_AVAILABLE=false if command -v upx >/dev/null 2>&1; then UPX_AVAILABLE=true echo "UPX detected, will compress binaries after build" else echo "UPX not found, binaries will not be compressed" fi # 与 GoReleaser 配置完全一致的平台组合 declare -A targets=( # Darwin (macOS) - 忽略 386 和 arm ["darwin-amd64"]="" ["darwin-arm64"]="" # Linux - 支持所有架构,包括 ARM 版本 ["linux-386"]="" ["linux-amd64"]="" ["linux-arm-v6"]="" # goarm=6 ["linux-arm-v7"]="" # goarm=7 ["linux-arm64"]="" # Windows - 忽略 arm (32位) ["windows-386"]=".exe" ["windows-amd64"]=".exe" ["windows-arm64"]=".exe" ) # build k=1 total=${#targets[@]} for target_key in "${!targets[@]}"; do time=$(date "+%Y-%m-%d %H:%M:%S") # 解析目标平台信息 if [[ "$target_key" == *"-arm-"* ]]; then # 处理 ARM 版本,如 linux-arm-v6, linux-arm-v7 IFS='-' read -r GOOS GOARCH GOARM_VER <<<"$target_key" GOARM=${GOARM_VER#v} # 移除 'v' 前缀 NAME_SUFFIX="armv$GOARM" else # 普通平台,如 linux-amd64, windows-386 IFS='-' read -r GOOS GOARCH <<<"$target_key" GOARM="" NAME_SUFFIX="$GOARCH" fi EXT="${targets[$target_key]}" # 构建符合 GoReleaser 规范的文件名 OUTPUT="$OUTPUT_DIR/${BIN_NAME}-${VERSION}-${GOOS}-${NAME_SUFFIX}${EXT}" # padding with spaces half of the terminal width COLUMNS=$(tput cols 2>/dev/null || echo 80) PADWIDTH=$((COLUMNS / 2)) OUTPUT_MSG=$(printf "%-${PADWIDTH}s" "Building $OUTPUT ...") prg=$(echo "scale=2; ($k * 100) / $total" | bc 2>/dev/null || echo "$k") printf "\r[%3.0f%%] %s%s" "$prg" "$OUTPUT_MSG" "$time" # 设置环境变量并构建 COMMIT=$(git rev-parse --short HEAD 2>/dev/null || echo "unknown") DATE=$(date -u +"%Y-%m-%dT%H:%M:%SZ") LDFLAGS="-s -w -X main.version=$VERSION -X main.commit=$COMMIT -X main.date=$DATE -X main.builtBy=manual" env GOOS=$GOOS GOARCH=$GOARCH GOARM=$GOARM go build -ldflags="$LDFLAGS" -trimpath -o "$OUTPUT" >/dev/null 2>&1 # compress with upx if available if [ "$UPX_AVAILABLE" = true ]; then OUTPUT_MSG=$(printf "%-${PADWIDTH}s" "Compressing $OUTPUT ...") time=$(date "+%Y-%m-%d %H:%M:%S") printf "\r[%3.0f%%] %s%s" "$prg" "$OUTPUT_MSG" "$time" upx --best --lzma -q "$OUTPUT" >/dev/null 2>&1 || echo -e "\nWarning: Failed to compress $OUTPUT" fi k=$((k + 1)) done printf "\r%-${PADWIDTH}s%s\n" "[100%] All done." "$(date "+%Y-%m-%d %H:%M:%S")" # reset env unset BIN_NAME VERSION OUTPUT_DIR targets time GOOS GOARCH GOARM EXT UPX_AVAILABLE unset COMMIT DATE LDFLAGS OUTPUT_MSG PADWIDTH COLUMNS prg k total target_key GOARM_VER NAME_SUFFIX # 生成校验和文件,文件名与 GoReleaser 一致 echo "" echo "📋 Generating checksums..." CHECKSUM_FILE="$OUTPUT_DIR/SHA256SUMS" cd "$OUTPUT_DIR" && sha256sum * | grep -v SHA256SUMS >"$(basename "$CHECKSUM_FILE")" && cd .. echo "✅ Build completed. Files generated in $OUTPUT_DIR" echo "📁 Total files: $(ls -1 "$OUTPUT_DIR" | wc -l) (including checksum)"