Go 1.18 will embed source version information into binaries
Since Go 1.13, Go has embedded information about the modules used
to build a program into its binary, and has reported them if you
go version -m ...' (release notes). This information has
historically included a variety of things,
including the path and module that the program was built from, an
indication of any module replacements being used, and a marker that
the program was being built from a source tree instead of with 'go
install ...@...'. However, it hasn't historically included any
information about the state of the source tree when you built from
In Go 1.18, this is changing due to issue 37475 and issue 35667. To quote from the draft release notes:
gocommand now embeds version control information in binaries including the currently checked-out revision and a flag indicating whether edited or untracked files are present. Version control information is embedded if the
gocommand is invoked in a directory within a Git or Mercurial repository, and the
mainpackage and its containing main module are in the same repository. This information may be omitted using the flag
gocommand embeds information about the build including build and tool tags (set with
-tags), compiler, assembler, and linker flags (like
-gcflags), whether cgo was enabled, and if it was, the values of the cgo environment variables (like
CGO_CFLAGS). This information may be omitted using the flag
(I don't know if the module and other information that will be embedded also includes information about the Go workspace you're in, if you're in one.)
At the moment this information is recorded in Go binaries in a form
that can be read by Go 1.17's '
go version -m', and probably this
also works for earlier versions (as I believe much of this information
is actually in the binary as text).
The current information is pretty verbose by default since cgo is generally enabled, and this adds five lines of output, even if the code being compiled didn't actually use it and you have no special environment variables set. I suspect that this won't get reduced before release; the Go team seems to like being comprehensive here.
If nothing else, having this information embedded into binaries will make it harder to lose track of what exactly you're running. Now you have a better chance of figuring out the provenance of some old Go binary that's been running in the corner for who knows how long. People who distribute binaries widely and build them doing funny things may now have more of those funny things be somewhat visible, though. Well, until they turn these features off with those documented flags.
(As threatened, Go 1.18 will only support
building programs in module mode, so this information only coming
go version -m' doesn't matter any more.)
Sidebar: What this extra information looks like today
Here is the additional output added by this, as reported by '
version -m' from the current development version:
build compiler gc build tags goexperiment.regabiwrappers,goexperiment.regabireflect,goexperiment.regabiargs build CGO_ENABLED true build CGO_CPPFLAGS build CGO_CFLAGS build CGO_CXXFLAGS build CGO_LDFLAGS build gitrevision 4f8a1b5f197fc69bc1252b32b5a8ed670ff557b6 build gituncommitted false
I wouldn't be surprised if some of the current build tags go away in the released version of Go 1.18, as some experiments are promoted out of that state.
Documentation on the current experiments is in the source code in
and can be gotten for your particular version of Go with '
goexperiment.Flags'. I'm not sure how you can find out the default
set of experiments enabled in your version of Go, but in the source
code this seems to be in the '
baseline' variable set in
ParseGOEXPERIMENT() function in internal/buildcfg/exp.go.
The current Go 1.18 build tags reported above appear to be this
baseline state on amd64.