diff --git a/README.md b/README.md
index e29ee56a49..4719e2d55e 100644
--- a/README.md
+++ b/README.md
@@ -457,7 +457,7 @@ go_library(
## go\_binary
```bzl
-go_binary(name, srcs, deps, data)
+go_binary(name, srcs, deps, data, stamp)
```
@@ -499,6 +499,20 @@ go_binary(name, srcs, deps, data)
List of files needed by this rule at runtime.
+
+ stamp |
+
+ Boolean; optional; default is False
+ Whether build information should be included in the generated binary.
+ Add @io_bazel_rules_go//buildstamp:go_default_library to
+ deps to access the build information . Build with
+ --workspace_status_command=./status.sh to add custom
+ information (using your own script).
+
+ tools/buildstamp/get_workspace_status in Bazel is a good template
+ for this that provides the Git revision and status.
+ |
+
diff --git a/buildstamp/BUILD b/buildstamp/BUILD
new file mode 100644
index 0000000000..4cea206c70
--- /dev/null
+++ b/buildstamp/BUILD
@@ -0,0 +1,9 @@
+load("//go:def.bzl", "go_library", "go_prefix")
+
+go_prefix("github.com/bazelbuild/rules_go")
+
+go_library(
+ name = "go_default_library",
+ srcs = glob(["*.go"]),
+ visibility = ["//visibility:public"],
+)
diff --git a/buildstamp/buildstamp.go b/buildstamp/buildstamp.go
new file mode 100644
index 0000000000..04c7523359
--- /dev/null
+++ b/buildstamp/buildstamp.go
@@ -0,0 +1,53 @@
+package buildstamp
+
+import "strings"
+
+var rawStampData string
+var stampData map[string]string
+
+func init() {
+ if len(rawStampData) > 0 {
+ stampData = make(map[string]string)
+ for _, line := range strings.Split(rawStampData, "\n") {
+ line = strings.TrimSpace(line)
+ if len(line) == 0 || strings.HasPrefix(line, "#") {
+ continue
+ }
+ var key, value string
+ if space := strings.IndexAny(line, " \t"); space == -1 {
+ key = line
+ } else {
+ key = line[:space]
+ value = strings.TrimSpace(line[space+1:])
+ }
+ stampData[key] = value
+ }
+ }
+}
+
+func HaveStampData() bool {
+ return stampData != nil
+}
+
+func RawStampData() string {
+ return rawStampData
+}
+
+func GetStampKeys() []string {
+ if stampData == nil {
+ return nil
+ }
+ keys := make([]string, 0, len(stampData))
+ for k, _ := range stampData {
+ keys = append(keys, k)
+ }
+ return keys
+}
+
+func GetStampValue(key string) (value string, ok bool) {
+ if stampData == nil {
+ return "", false
+ }
+ value, ok = stampData[key]
+ return
+}
diff --git a/go/def.bzl b/go/def.bzl
index 48637e51ca..de1fdf7e57 100644
--- a/go/def.bzl
+++ b/go/def.bzl
@@ -352,7 +352,7 @@ def _short_path(f):
return f.path[len(prefix):]
def emit_go_link_action(ctx, importmap, transitive_libs, cgo_deps, lib,
- executable, x_defs={}):
+ executable, x_defs={}, stamp=False):
"""Sets up a symlink tree to libraries to link together."""
out_dir = executable.path + ".dir"
out_depth = out_dir.count('/') + 1
@@ -396,6 +396,15 @@ def emit_go_link_action(ctx, importmap, transitive_libs, cgo_deps, lib,
if x_defs:
link_cmd += [" -X %s='%s' " % (k, v) for k,v in x_defs.items()]
+ if stamp:
+ stamp_cmd = ("LINKSTAMP=$(cat '%s' '%s')" %
+ (ctx.version_file.path, ctx.info_file.path))
+ link_cmd += ['-X github.com/bazelbuild/rules_go/buildstamp.rawStampData="$LINKSTAMP"']
+ stamp_deps = [ctx.version_file, ctx.info_file]
+ else:
+ stamp_cmd = ""
+ stamp_deps = []
+
# workaround for a bug in ld(1) on Mac OS X.
# http://lists.apple.com/archives/Darwin-dev/2006/Sep/msg00084.html
# TODO(yugui) Remove this workaround once rules_go stops supporting XCode 7.2
@@ -416,6 +425,7 @@ def emit_go_link_action(ctx, importmap, transitive_libs, cgo_deps, lib,
cmds += ["export PATH=$PATH:/usr/bin"]
cmds += [
"export GOROOT=$(pwd)/" + ctx.file.go_tool.dirname + "/..",
+ stamp_cmd,
"cd " + out_dir,
' '.join(link_cmd),
"mv -f " + _go_importpath(ctx) + " " + ("../" * out_depth) + executable.path,
@@ -424,7 +434,7 @@ def emit_go_link_action(ctx, importmap, transitive_libs, cgo_deps, lib,
f = _emit_generate_params_action(cmds, ctx, lib.path + ".GoLinkFile.params")
ctx.action(
- inputs = (list(transitive_libs) + [lib] + list(cgo_deps) +
+ inputs = (list(transitive_libs) + [lib] + list(cgo_deps) + stamp_deps +
ctx.files.toolchain + ctx.files._crosstool),
outputs = [executable],
executable = f,
@@ -438,12 +448,13 @@ def go_binary_impl(ctx):
lib_out = ctx.outputs.lib
emit_go_link_action(
- ctx,
- transitive_libs=lib_result.transitive_go_library_object,
- importmap=lib_result.transitive_go_importmap,
- cgo_deps=lib_result.transitive_cgo_deps,
- lib=lib_out, executable=executable,
- x_defs=ctx.attr.x_defs)
+ ctx,
+ transitive_libs=lib_result.transitive_go_library_object,
+ importmap=lib_result.transitive_go_importmap,
+ cgo_deps=lib_result.transitive_cgo_deps,
+ lib=lib_out, executable=executable,
+ x_defs=ctx.attr.x_defs,
+ stamp=ctx.attr.stamp)
runfiles = ctx.runfiles(collect_data = True,
files = ctx.files.data)