构建与发布
Lite / Full 双变体、12 个平台交叉编译、Docker、GoReleaser 与 CI/CD 全流程。
两种构建变体一览
- Lite 默认:体积约 5MB,不含指纹库,首次查询时自动下载——适合对体积敏感的分发场景。
- Full 需 -tags:体积约 8MB,内嵌 700+ 指纹,完全离线可用——适合内网/离线环境。
平台支持矩阵 12 platforms
下表列出所有 GOOS × GOARCH 组合的官方支持状态。✓ 表示 GoReleaser 与 CI 矩阵默认构建,△ 表示需手动触发或自备工具链,✗ 表示上游 Go 工具链不支持。
| GOOS \ GOARCH | amd64 | arm64 | 386 | arm | riscv64 | 备注 |
|---|---|---|---|---|---|---|
| linux 主力 | ✓ | ✓ | ✓ | ✓ | ✓ | 全架构支持,CGO 可禁用 |
| darwin macOS | ✓ | ✓ | ✗ | ✗ | ✗ | 仅 Intel / Apple Silicon |
| windows Win | ✓ | ✓ | ✓ | ✗ | ✗ | 输出 .exe,zip 打包 |
| freebsd BSD | ✓ | ✓ | ✗ | ✗ | ✗ | 社区需求驱动 |
共 12 个有效组合 × 2 模式(Lite/Full)= 24 个预构建二进制 24 binaries,由
.goreleaser.yml的ignore列表过滤掉 8 个不支持组合后得到。
架构命名映射
GoReleaser 归档名按人类可读方式重命名:amd64→x86_64、arm64→aarch64、386→i386、arm→armv6h,与上表 Go 原生 GOARCH 一一对应。下载 Release 资产时请认准归档名后缀。
交叉编译必须禁用 CGO
本项目所有二进制均设 CGO_ENABLED=0 纯静态链接,以兼容 musl/Alpine 与最小镜像。若你本地启用了 CGO(默认开启),交叉编译会因缺少目标平台 gcc 而失败。手动构建请显式设置:
CGO_ENABLED=0 GOOS=linux GOARCH=arm64 go build -tags embed_fingerprints -o iconhash .构建变体
| 命令 | 产物 | 指纹 |
|---|---|---|
make build | iconhash (Lite) ~5MB | 运行时下载 |
make build-full | iconhash (Full) ~8MB | 内嵌 |
make build-race | 带竞态检测 (Full) 调试用 | 内嵌 |
Full 构建必须显式传 -tags embed_fingerprints
直接执行 make build 不会内嵌指纹。要得到离线可用的 Full 二进制,必须使用 make build-full 或手动加上构建标签 -tags embed_fingerprints,否则二进制仍会在首次查询时尝试联网下载指纹。
构建命令分组 Lite / Full / Docker
三组场景的核心命令一行即可,完整带版本注入的等价命令折叠在下方。
Lite 构建核心命令
make build # 等价 go build,产物 ~5MB完整 Lite 命令(含 ldflags 注入)
go build \
-trimpath \
-ldflags "-s -w \
-X github.com/cyberspacesec/iconhash-skills/cmd.Version=$(git describe --tags --always --dirty) \
-X github.com/cyberspacesec/iconhash-skills/cmd.BuildDate=$(date +%FT%T%z) \
-X github.com/cyberspacesec/iconhash-skills/cmd.BuildHash=$(git rev-parse --short HEAD)" \
-o iconhash .产物不含指纹,首次查询时自动从远端拉取 fingerprints.json。
Full 构建核心命令
make build-full # -tags embed_fingerprints,产物 ~8MB,离线可用完整 Full 命令(含 -tags 与 ldflags)
go build \
-trimpath \
-tags embed_fingerprints \
-ldflags "-s -w \
-X github.com/cyberspacesec/iconhash-skills/cmd.Version=$(git describe --tags --always --dirty) \
-X github.com/cyberspacesec/iconhash-skills/cmd.BuildDate=$(date +%FT%T%z) \
-X github.com/cyberspacesec/iconhash-skills/cmd.BuildHash=$(git rev-parse --short HEAD)" \
-o iconhash .指纹通过 //go:embed 编译期内嵌,运行时无网络依赖。
Docker 构建核心命令
make docker-build # 基于 golang:1.25 多阶段,最终镜像极小完整 Docker 命令链
# 构建并打 latest 标签
make docker-build
# 运行 Lite(运行时下载指纹)
docker run --rm cyberspacesec/iconhash:latest identify https://example.com
# 运行 Full(环境变量切换内嵌指纹)
docker run --rm -e ICONHASH_EMBED_FINGERPRINTS=1 cyberspacesec/iconhash:latest identify https://example.com
# 作为 HTTP 服务
docker run --rm -p 8000:8000 cyberspacesec/iconhash:latest server
# 健康检查
curl http://localhost:8000/health
# 推送到镜像仓库
docker login && make docker-push本地构建
# Lite
make build
# Full(离线版)
make build-full注入的版本信息通过 cmd.Version / cmd.BuildDate / cmd.BuildHash,iconhash --version 可查看。
验证构建产物
构建完成后,建议立即运行 ./iconhash --version 确认版本号、构建日期、Commit Hash 都已正确注入。若三项均为空,说明 ldflags 未生效,请检查 Makefile 中的 LDFLAGS 变量。
手动执行 go build(不依赖 Makefile)
若需要脱离 Makefile 手动构建,等价命令如下:
# Lite(无指纹内嵌)
go build -o iconhash .
# Full(内嵌指纹,必须带 -tags)
go build -tags embed_fingerprints -o iconhash .
# 注入版本信息
go build -ldflags "-X iconhash-skills/cmd.Version=2.0.0 \
-X iconhash-skills/cmd.BuildDate=$(date -u +%Y-%m-%dT%H:%M:%SZ) \
-X iconhash-skills/cmd.BuildHash=$(git rev-parse --short HEAD)" \
-tags embed_fingerprints -o iconhash .交叉编译
通过 GOOS / GOARCH 环境变量交叉编译,覆盖 12 个平台 12 platforms:
平台支持矩阵
GOOS × GOARCH 组合图
下图展示全部 20 个原始 GOOS×GOARCH 组合,绿色为 CI/GoReleaser 默认构建的 12 个有效组合,灰色为 ignore 过滤掉的 8 个不支持组合。
共 12 个有效组合 × 2 模式(Lite/Full)= 24 个预构建二进制 24 binaries。
macOS / Windows 上的 386 与 arm
macOS 与 FreeBSD 对 386 / arm / riscv64 标记为 ✗,原因是上游 Go 工具链在这些组合下缺失关键系统调用支持或 CGO 依赖。若你的场景确实需要,可尝试 GOOS=darwin GOARCH=arm64 等 Go 官方支持的组合。
手动交叉编译
各平台手动交叉编译命令
# Linux ARM64 Full
GOOS=linux GOARCH=arm64 go build -tags embed_fingerprints -o iconhash-full-linux-arm64 .
# Windows AMD64 Lite
GOOS=windows GOARCH=amd64 go build -o iconhash-windows-amd64.exe .
# macOS ARM64 Full(Apple Silicon)
GOOS=darwin GOARCH=arm64 go build -tags embed_fingerprints -o iconhash-full-darwin-arm64 .
# Linux RISC-V 64 Lite
GOOS=linux GOARCH=riscv64 go build -o iconhash-linux-riscv64 .
# FreeBSD AMD64 Lite
GOOS=freebsd GOARCH=amd64 go build -o iconhash-freebsd-amd64 .Make 批量构建
make release-lite # 6 平台 Lite
make release-full # 6 平台 Full
make release-all # 全部 12+12release-all 会比较耗时
make release-all 会遍历 24 个组合做交叉编译,在普通笔记本上约需 3–5 分钟。若只发布某一类,优先使用 release-lite 或 release-full。
Docker golang:1.25
# 构建
make docker-build
# 运行
docker run --rm cyberspacesec/iconhash:latest identify https://example.com
# 推送
make docker-push完整 Docker 构建链路
镜像基于 golang:1.25 多阶段构建,最终运行镜像仅包含二进制与必要 CA 证书,体积很小:
# 1. 本地构建镜像
make docker-build
# 2. 运行 Lite(运行时下载指纹)
docker run --rm cyberspacesec/iconhash:latest identify https://example.com
# 3. 运行 Full(内嵌指纹,离线可用)
docker run --rm -e ICONHASH_EMBED_FINGERPRINTS=1 cyberspacesec/iconhash:latest identify https://example.com
# 4. 作为 HTTP 服务运行
docker run --rm -p 8000:8000 cyberspacesec/iconhash:latest server
# 5. 健康检查
curl http://localhost:8000/health
# 6. 登录并推送到镜像仓库
docker login
make docker-push生产部署请使用 Full 镜像
若部署在受限网络或内网,建议使用基于 Full 构建的镜像,避免容器启动后因无法下载指纹而导致首次查询失败。Lite 镜像则适合对体积有极致要求的 CI/临时场景。
目录结构
CI/CD 流水线 GitHub Actions
GitHub Actions 自动化全流程:
CI/CD 全链路流水线
下图展示从代码提交到生产部署的完整链路:build → test → release → deploy 四阶段全貌。
CI 任务详情
build.yml 关键片段
name: build
on:
push:
branches: [main]
pull_request:
jobs:
test:
runs-on: ubuntu-latest
strategy:
matrix:
mode: [lite, full]
steps:
- uses: actions/checkout@v4
- uses: actions/setup-go@v5
with:
go-version: '1.25'
- run: go test -race ./...
build:
strategy:
matrix:
goos: [linux, darwin, windows, freebsd]
goarch: [amd64, arm64, '386', arm, riscv64]
exclude:
- goos: darwin
goarch: '386'
# ... 其他不支持的组合
steps:
- run: go build -tags ${{ matrix.mode == 'full' && 'embed_fingerprints' || '' }}
docker:
runs-on: ubuntu-latest
steps:
- run: make docker-build触发条件
- 代码变更(
*.go/Makefile/go.mod等)→ 触发build.yml的test/lint/build/docker全套作业。 website/目录变更 → 触发deploy-website.yml,构建站点并部署到gh-pages分支。
网站部署流水线
版本与发布 GoReleaser
版本信息通过 ldflags 注入:
LDFLAGS=-ldflags "-X .../cmd.Version=${VERSION} \
-X .../cmd.BuildDate=${DATE} \
-X .../cmd.BuildHash=${COMMIT}"GoReleaser 配置片段(.goreleaser.yml)
GoReleaser 通过两个 builds 条目分别产出 Lite / Full,并使用 ignore 列表过滤上游不支持的组合。关键片段如下:
version: 2
project_name: iconhash
before:
hooks:
- go mod tidy
builds:
# Lite — 不内嵌指纹
- id: iconhash-lite
binary: iconhash
main: .
flags: [-trimpath]
ldflags:
- -s -w
- -X github.com/cyberspacesec/iconhash-skills/cmd.Version={{.Version}}
- -X github.com/cyberspacesec/iconhash-skills/cmd.BuildDate={{.Date}}
- -X github.com/cyberspacesec/iconhash-skills/cmd.BuildHash={{.ShortCommit}}
env: [CGO_ENABLED=0]
goos: [linux, darwin, windows, freebsd]
goarch: [amd64, arm64, "386", arm, riscv64]
ignore:
- { goos: darwin, goarch: "386" }
- { goos: darwin, goarch: arm }
- { goos: darwin, goarch: riscv64 }
- { goos: windows, goarch: arm }
- { goos: windows, goarch: riscv64 }
- { goos: freebsd, goarch: "386" }
- { goos: freebsd, goarch: arm }
- { goos: freebsd, goarch: riscv64 }
# Full — 内嵌指纹
- id: iconhash-full
binary: iconhash-full
main: .
flags: [-trimpath]
tags: [embed_fingerprints] # 关键差异:内嵌指纹
ldflags:
- -s -w
- -X github.com/cyberspacesec/iconhash-skills/cmd.Version={{.Version}}
- -X github.com/cyberspacesec/iconhash-skills/cmd.BuildDate={{.Date}}
- -X github.com/cyberspacesec/iconhash-skills/cmd.BuildHash={{.ShortCommit}}
env: [CGO_ENABLED=0]
goos: [linux, darwin, windows, freebsd]
goarch: [amd64, arm64, "386", arm, riscv64]
ignore:
- { goos: darwin, goarch: "386" }
# ... 与 lite 相同的 ignore 列表
archives:
- id: lite
builds: [iconhash-lite]
name_template: >-
iconhash_lite_{{ .Os }}_{{ if eq .Arch "amd64" }}x86_64
{{- else if eq .Arch "arm64" }}aarch64
{{- else if eq .Arch "386" }}i386
{{- else if eq .Arch "arm" }}armv6h
{{- else }}{{ .Arch }}{{ end }}
format_overrides:
- goos: windows
format: zip
files: [README.md, LICENSE, SKILLS.md, data/fingerprints.json, data/fingerprints.version.json]
changelog:
sort: asc
filters:
exclude: ["^docs:", "^test:", "^chore:", "merge conflict"]
groups:
- { title: "🚀 Features", regexp: '^.*?feat(\([[:word:]]+\))??!?:.+$', order: 0 }
- { title: "🐛 Bug Fixes", regexp: '^.*?fix(\([[:word:]]+\))??!?:.+$', order: 1 }
- { title: "🔧 Other Changes", order: 999 }本地测试发布流程(不真正发版):
goreleaser release --clean --snapshot # 快照构建到 dist/
goreleaser build --clean --single-target # 仅当前平台单构建发布前检查清单
- [ ]
main分支处于干净状态,所有 PR 已合并 - [ ] 本地
make test与make release-all均通过 - [ ]
VERSION/DATE/COMMIT变量正确 - [ ]
.goreleaser.yml中的目标平台与当前支持矩阵一致 - [ ] Docker Hub 登录凭据已在 GitHub Secrets 中配置
验证构建
./iconhash --version
./iconhash identify https://example.com
./iconhash server &
curl http://localhost:8000/health一步完成全部验证
可以用下面的命令一次性跑完整条验证链,确认构建产物在版本、命令、识别、HTTP 服务四方面均正常:
./iconhash --version && \
./iconhash identify https://example.com && \
(./iconhash server &) && \
sleep 1 && \
curl -s http://localhost:8000/health && \
echo "✅ 构建验证通过"常见失败信号
--version输出为空 →ldflags未注入,回看 本地构建。identify报指纹缺失 → 使用了 Lite 构建且无法联网,改用make build-full。/health返回非 200 → 端口被占用或服务启动失败,检查server子命令日志。
Makefile 目标速查 16 targets
| 目标 | 作用 | 标记 |
|---|---|---|
make build build-lite | Lite 构建 | Lite |
make build-lite | Lite 构建别名 | ~5MB |
make build-full build-full | Full 构建(内嵌指纹) | Full |
make build-race | 竞态检测构建 | -race |
make build-gui | 渲染并内嵌 GUI 资源 | gui |
make test | 运行测试 | go test |
make test-coverage | 覆盖率报告 | html |
make validate-skills | 校验 skills 结构 | lint |
make release-lite | 6 平台 Lite 发布构建 | 6 bins |
make release-full | 6 平台 Full 发布构建 | 6 bins |
make release-all release-all | 全平台发布构建 | 12 bins |
make docker-build docker-build | Docker 镜像构建 | image |
make docker-push | 推送镜像到仓库 | push |
make docker-run | 容器内运行工具 | run |
make render-docs | 渲染 SVG 图表 | svg |
make clean | 清理构建产物 | clean |
make install | 安装到 GOBIN | go install |
下一篇:FAQ。