Compile Time Variables in Go

When I and others ship software releases, I want to embed build information. In particular I find embedding the VCS revision at build time, this makes tracking down bugs in releases significantly easier than version numbers. Historically this was achieved by generating a file in the Makefile. You may have been generating files similar to the one below:

// THIS FILE IS AUTOMATICALLY GENERATED. DO NOT MODIFY MANUALLY.

package main

var BuildRevision string = "c3ac02d83c93989907fe07156246d4cc7227ead3"

While this works, we can be smarter. I recently discovered the -X option of the Go linker. This option allows you to overwrite the value defined for a string in a package. During builds we can pass extra linker flags using -ldflags. To use we must define an empty global string somewhere within our package, then we would pass -X importpath.name=value to the linker. Example:

package main

import (
    "fmt"
)

var BuildRevision string = ""

func main() {
    fmt.Println("Build Revision:", BuildRevision)
}

As you would expect, if you ran the above you would simply get an empty result for the build revision. Lets run a build both with and without the linker options.

$ go run main.go
Build Revision:

$ go run -ldflags="-X main.BuildRevision=abc123" main.go
Build Revision: abc123

With the above we can replace the file generation from our Makefile completely, making the build process simpler.

Tags: golang

← back to James Cunningham