如何完全静态编译GO

Go 语言天生支持跨平台编译,并且其标准库几乎不依赖系统动态库,所以在大多数场景下,它编译出来的二进制文件几乎可以直接丢到任何机器运行

但实际开发中,我们经常遇到两个问题:

  1. 如何完全静态编译?
    • 确保 ldd 显示 not a dynamic executable,不依赖宿主机动态库。
  2. 如何交叉编译到不同平台?
    • 例如 Mac 上编译 Linux/Windows/ARM64 的二进制。

这篇文章会从基础概念讲起,逐步深入,并附带一个一键多平台静态编译脚本,让我们少踩坑。

1. 基础概念

  • 静态编译 = 把所有依赖库都编进一个二进制,丢到任何机器都能跑
  • 动态编译 = 程序运行时还需要宿主机的动态库(如 libc.so.6)
  • 交叉编译 = 在 A 平台上编译 B 平台的程序(比如 Mac 编译 Linux 版)

Go 天生适合静态编译,因为:

• 纯 Go 代码不依赖外部 libc
• 关闭 CGO 后编译结果天然是静态的

只有当项目用了 CGO(如 sqlite、openssl)才会出现动态依赖,需要额外处理。

2. 完全静态编译

纯 Go 项目(最简单)

CGO_ENABLED=0 go build -ldflags="-s -w" -o app .
CGO_ENABLED=0 关闭 C 依赖 → 天然静态
• -ldflags="-s -w" 去掉符号表,减小体积

验证:

ldd app  # not a dynamic executable ✅

有 CGO 依赖(sqlite、openssl 等)

默认会动态链接 glibc,要用 musl 完全静态化:

CC=musl-gcc CGO_ENABLED=1 go build -ldflags="-linkmode external -extldflags -static" -o app .
• musl-gcc 是轻量 libc,适合静态链接
• -extldflags -static 让外部链接器打包所有依赖

验证:

ldd app  # not a dynamic executable ✅

3. 交叉编译(跨平台 + 静态)

Go 内置交叉编译能力,只需 GOOS/GOARCH:


# Linux AMD64
GOOS=linux GOARCH=amd64 CGO_ENABLED=0 go build -o app-linux-amd64 .

# Linux ARM64(树莓派)
GOOS=linux GOARCH=arm64 CGO_ENABLED=0 go build -o app-linux-arm64 .

# Windows
GOOS=windows GOARCH=amd64 CGO_ENABLED=0 go build -o app-windows-amd64.exe

# macOS ARM64
GOOS=darwin GOARCH=arm64 CGO_ENABLED=0 go build -o app-mac-arm64

⚠️ 如果必须用 CGO,交叉编译就需要额外交叉工具链(如 aarch64-linux-musl-gcc)。

4. Docker 结合静态编译

•	动态编译的程序 → 容器镜像必须带 libc(debian、alpine)
•	静态编译的程序 → 直接放 FROM scratch,镜像只有几 MB

推荐:

FROM golang:1.22-alpine AS builder
RUN apk add --no-cache build-base musl-dev
WORKDIR /src
COPY . .
RUN CGO_ENABLED=0 go build -ldflags="-s -w" -o /out/app .

FROM scratch
COPY --from=builder /out/app /app
ENTRYPOINT ["/app"]

5. 一键多平台静态编译脚本

#!/usr/bin/env bash
set -e

APP="myapp"            # 你的程序名
OUT="dist"             # 输出目录
PLATFORMS=("linux/amd64" "linux/arm64" "darwin/arm64" "windows/amd64")

# 是否启用 CGO(0=纯Go,1=需要C依赖)
USE_CGO=${USE_CGO:-0}

echo "📦 Building $APP for: ${PLATFORMS[*]}"
echo "🔧 CGO Mode: ${USE_CGO}"

rm -rf "$OUT" && mkdir -p "$OUT"

for p in "${PLATFORMS[@]}"; do
  GOOS=${p%/*}
  GOARCH=${p#*/}

  BIN="$OUT/$APP-$GOOS-$GOARCH"
  [[ $GOOS == "windows" ]] && BIN="$BIN.exe"

  echo -e "\n==> 🚀 Building for $GOOS/$GOARCH ..."

  if [[ "$USE_CGO" == "1" ]]; then
    if [[ "$GOOS" == "linux" ]]; then
      echo "🔗 Linux CGO enabled + musl static build"
      CC=musl-gcc \
      CGO_ENABLED=1 \
      GOOS=$GOOS GOARCH=$GOARCH \
      go build -ldflags="-linkmode external -extldflags -static -s -w" -o "$BIN" .

    elif [[ "$GOOS" == "windows" ]]; then
      echo "🔗 Windows CGO static build (MinGW-w64 required)"
      CC=x86_64-w64-mingw32-gcc \
      CGO_ENABLED=1 \
      GOOS=$GOOS GOARCH=$GOARCH \
      go build -ldflags="-extldflags=-static -s -w" -o "$BIN" .

    else
      echo " ⚠️  CGO cross-compile for $GOOS not supported, falling back to pure Go"
      CGO_ENABLED=0 GOOS=$GOOS GOARCH=$GOARCH \
      go build -ldflags="-s -w" -o "$BIN" .
    fi

  else
    echo "✅ Pure Go build (CGO disabled)"
    CGO_ENABLED=0 GOOS=$GOOS GOARCH=$GOARCH \
    go build -ldflags="-s -w" -o "$BIN" .
  fi

  # ✅ 验证是否静态(仅 Linux / Windows)
  if [[ "$GOOS" == "linux" && -x "$BIN" ]]; then
    echo "🔍 Checking binary type (ldd):"
    if command -v ldd >/dev/null; then
      ldd "$BIN" || echo "✅ Not a dynamic executable"
    fi
  fi

  if [[ "$GOOS" == "windows" && -x "$BIN" ]]; then
    echo "🔍 Checking Windows deps (objdump):"
    if command -v x86_64-w64-mingw32-objdump >/dev/null; then
      x86_64-w64-mingw32-objdump -p "$BIN" | grep DLL || echo "✅ No extra DLL deps"
    else
      echo "(no objdump, skip check)"
    fi
  fi

  echo "✅ $BIN built."
done

echo -e "\n🎉 All binaries are in $OUT/"

执行:

chmod +x build-all.sh 
./build-all.sh # or USE_CGO=1 ./build-all.sh

最终你会得到:

dist/
  ├── myapp-linux-amd64
  ├── myapp-linux-arm64
  ├── myapp-darwin-amd64
  ├── myapp-darwin-arm64
  ├── myapp-windows-amd64.exe

可以分发给对应的二进制平台即可

其他:

musl 是 一个轻量的 C 标准库实现,主要用来替代传统的 glibc。

Go 编译器在用 CGO 时,需要链接 C 运行库(libc),默认是 glibc,但 glibc 的动态库在不同 Linux 发行版版本不同,容易产生兼容性问题。

musl 的特点是:

•	体积小(适合嵌入式和容器)
•	设计简洁、依赖少
•	支持完整静态链接,方便做“丢哪都能跑”的程序
•	常用在 Alpine Linux 这种极简系统中

所以,如果你想让一个含 CGO 的 Go 程序 完全静态,就得用 musl-gcc 替代 gcc,这样 libc 也能被编进二进制里。

glibc vs musl 直观对比

项目glibcmusl
体积
兼容性最通用,几乎所有 Linux 默认用轻量,偏向容器/嵌入式
默认是否动态链接
是否易做静态编译❌ 麻烦✅ 非常容易
适用场景桌面、服务器Alpine、scratch 镜像、IoT

 

转载自https://juejin.cn/post/7529434797891436582

 

whisper-live

 docker run -d   --name whisper-live -p 9089:8080  -p 9090:9090   hwdsl2/whisper-live-server
 docker logs whisper-live
WhisperLive Docker - https://github.com/hwdsl2/docker-whisper-live

Starting WhisperLive real-time speech-to-text server...
  Model:          base
  Language:       auto
  WebSocket port: 9090
  REST API port:  8000
  Max clients:    4
  VAD:            true

Note: Model 'base' not found in cache. It will be downloaded
      from HuggingFace on first client connection. This may take several minutes.

The cache for model files in Transformers v4.22.0 has been updated. Migrating your old cache. This is a one-time only operation. You can interrupt this and resume the migration later on by calling `transformers.utils.move_cache()`.
0it [00:00, ?it/s]
INFO:root:✅ OpenAI-Compatible API started on http://0.0.0.0:8000
INFO:     Started server process [90]
INFO:     Waiting for application startup.
INFO:     Application startup complete.
INFO:     Uvicorn running on http://0.0.0.0:8000 (Press CTRL+C to quit)
INFO:     127.0.0.1:33366 - "GET /docs HTTP/1.1" 200 OK

===========================================================
 WhisperLive real-time transcription server is ready
===========================================================
 Model:          base
 WebSocket:      ws://x.x.x.x:9090
 REST API:       http://x.x.x.x:8000
===========================================================

Connect a client (WebSocket streaming):
  ws://x.x.x.x:9090

Transcribe a file (REST API):
  curl http://x.x.x.x:8000/v1/audio/transcriptions \
    -F file=@audio.mp3 -F model=whisper-1

Interactive API docs: http://x.x.x.x:8000/docs

To set up HTTPS, see: Using a reverse proxy
  https://github.com/hwdsl2/docker-whisper-live#using-a-reverse-proxy

Setup complete.

AI-TTS-TEST-测试

#TEST-kokoro
docker run --rm -p 8880:8880 ghcr.io/hsiang-han/kokoro-fastapi-zh-cpu:latest
#Model warmed up on cpu: kokoro_v1
#Running on CPU
#103 voice packs loaded
#Beta Web Player: http://0.0.0.0:8880/web/
#or http://localhost:8880/web/

#TEST-Coqui
# Voice Synthesis Project with Coqui TTS and FastAPI
# https://github.com/zlKingado/tts-web-api/tree/main
# docker run --rm -p 5001:5001 -v ${PWD}/cached_audio:/app/cached_audio tts-api-cpu