go build -ldflags: Inject Version Strings in CI
go build -ldflags passes options to the Go linker, most commonly -X to set a package variable (like a version) and -s -w to strip debug info for a smaller binary.
Release pipelines stamp the version and commit into the binary at build time. -ldflags "-X ..." does exactly that without a code change, and -trimpath keeps builds reproducible.
What it does
go build -ldflags forwards a quoted string of flags to the linker. -X importpath.name=value overrides a string variable; -s omits the symbol table and -w omits DWARF debug info; -trimpath (a build flag, not an ldflag) removes absolute paths from the binary.
Common usage
go build -ldflags "-X main.version=$(git describe --tags) -s -w" -o app ./cmd/app
go build -trimpath -ldflags "-X 'main.commit=$GIT_SHA'" ./...
CGO_ENABLED=0 go build -ldflags "-extldflags '-static'" ./cmd/appFlags
| Flag | What it does |
|---|---|
| -ldflags "-X p.v=val" | Set string variable v in package p at link time |
| -ldflags "-s -w" | Strip symbol table and DWARF for a smaller binary |
| -trimpath | Remove local file system paths from the binary |
| -ldflags "-extldflags '-static'" | Pass flags to the external C linker |
| -o <file> | Write the output binary to a path |
In CI
Cache the Go build cache (go env GOCACHE, default ~/.cache/go-build) and the module cache (~/go/pkg/mod) keyed on go.sum to speed rebuilds. Use -trimpath for reproducible release binaries. Set CGO_ENABLED=0 for a static, distroless-friendly binary when you have no cgo dependencies.
Common errors in CI
"cannot use -X with non-string variable" means the target is not a string (only string vars can be set). "missing value in -X=...; use -X=name=value" means a malformed -X. "-X main.version: unknown var" means the importpath is wrong (it is the package path, not the file). Static linking with cgo gives "warning: Using 'getaddrinfo' in statically linked applications".