Build Flags

PUBLISHED ON 2021-08-02 — C, REVERSE ENGINEERING, TOOLS

Example Usage in Dockerfiles

# Standard
RUN GOOS=linux GOARCH=amd64 CGO_ENABLED=0 go build -o app.bin ./cmd

# Slightly smaller
RUN GOOS=linux GOARCH=amd64 CGO_ENABLED=0 go build -ldflags="-w -s" -o app.bin ./cmd

# With version number
RUN CGO_ENABLED=0 go build -a -ldflags "-X main.buildVersion=$(git describe --tags) -extldflags '-static' -s -w" -o app.bin ./cmd

# With build info
RUN COMMIT_HASH=`git describe --exact-match --abbrev=0 --tags $(git rev-parse HEAD) 2> /dev/null || git rev-parse --short HEAD` && \
  BUILD_DATE=`date --iso-8601=seconds` && \
  LDFLAGS="-w -s -X main.commitHash=${COMMIT_HASH} -X main.buildDate=${BUILD_DATE}" && \
  GOOS=linux GOARCH=amd64 CGO_ENABLED=0 go build -ldflags="${LDFLAGS}" -o app.bin ./cmd

Variables

  • GOOS=x
    • Popular: linux, darwin
    • Useful for cross platform builds
  • GOARCH=x
    • Popular: 386, amd64 and arm, arm64
    • Useful for cross platform builds
    • Not all combinations of GOOS and GOARCH are available
      • go tool dist list
  • CGO_ENABLED=x
    • Popular: Just disable it: 0
    • Some things are only availabe as C libraries however, and setting it to 1 will be required to compile
      • This requires a working C compilation toolchain for the target platform
      • Fine tuning might be needed, eg. CC=aarch64-linux-musl-gccgo

Options

  • o
    • Set name of output binary
  • a
    • Force rebuilding of packages that are already up-to-date
  • ldflags
    • Arguments to pass on each go tool link invocation
    • w = Omit the DWARF debugging info
      • Standardized debugging data format
      • This decreases the output binary file size, but not by much (eg 3.7kb of 25mb)
    • s = Omit the DWARF debugging info and the symbol and string tables
      • s includes w but in real life you often see both flags passed
      • The main benefit is to make reverse engineering the binary a bit harder, by not leaking info like symbol/function/variable names
      • It probably also makes the trace output of a crashed golang executable incomprehensible
    • x = Overwrite variable at build time
      • Often used to hardcode the build/version number during a CI run
      • go build -ldflags="-X 'main.Version=v1.0.0'" assumes a package level variable “Version” exists in the main package
      • Sub-packages are accessible via go build -ldflags="-X 'package_path.variable_name=new_value'"
    • -extldflags '-static'
      • Set space-separated flags to pass to the external linker
      • See documentation of that external linker, often the GNU linker ld
        • -static means do not link against shared libraries