[build][go] use GOCACHE for builds

GOCACHE allows for caching build artifacts and test results across
builds. As of Go 1.12, GOCACHE is required to be set if a user cache
directory cannot be determined (which is done using $HOME or
$XDG_CACHE_HOME). Neither of these environment variables are set during
our builds (and if they are, it's not necessarily likely that we would
like to use them), so we must set GOCACHE to build Go 1.12.

This change introduces a declared_arg to set the go cache directory,
which defaults to the root build directory joined with ".gocache". If
overridden, this argument must be a full path.

Change-Id: I0e509e498cb60772cbd94456afac6e1fe757e953
diff --git a/go/build.py b/go/build.py
index 5d05712..a808d80 100755
--- a/go/build.py
+++ b/go/build.py
@@ -32,6 +32,8 @@
     parser.add_argument('--current-os', help='Target operating system.',
                         choices=['fuchsia', 'linux', 'mac', 'win'], required=True)
     parser.add_argument('--go-root', help='The go root to use for builds.', required=True)
+    parser.add_argument('--go-cache', help='Cache directory to use for builds.',
+                        required=False)
     parser.add_argument('--is-test', help='True if the target is a go test',
                         default=False)
     parser.add_argument('--go-dep-files',
@@ -53,6 +55,14 @@
                         action='store_true')
     args = parser.parse_args()
 
+    try:
+        os.makedirs(args.go_cache)
+    except OSError as e:
+        if e.errno == errno.EEXIST and os.path.isdir(args.go_cache):
+            pass
+        else:
+            raise
+
     goarch = {
         'x64': 'amd64',
         'arm64': 'arm64',
@@ -111,6 +121,7 @@
     # Some users have GOROOT set in their parent environment, which can break
     # things, so it is always set explicitly here.
     env['GOROOT'] = build_goroot
+    env['GOCACHE'] = args.go_cache
     env['CGO_CFLAGS'] = "--sysroot=" + args.sysroot
 
     if goos == 'fuchsia':
diff --git a/go/go_build.gni b/go/go_build.gni
index 0d4e274..c55d77d 100644
--- a/go/go_build.gni
+++ b/go/go_build.gni
@@ -8,6 +8,17 @@
 import("//build/sdk/sdk_atom.gni")
 import("//build/testing/test_spec.gni")
 
+# Declared Arguments:
+#
+#   gocache_dir
+#     Directory GOCACHE environment variable will be set to. This directory
+#     will have build and test results cached, and is safe to be written to
+#     concurrently. If overridden, this directory must be a full path.
+#
+declare_args() {
+  gocache_dir = rebase_path("$root_out_dir/.gocache")
+}
+
 # A template for an action that builds a Go binary. Users should instead use the
 # go_binary or go_test rules.
 #
@@ -91,6 +102,8 @@
           get_label_info("//default($shlib_toolchain)", "root_out_dir")),
       "--sysroot",
       sysroot,
+      "--go-cache",
+      gocache_dir,
     ]
 
     if (defined(invoker.skip_vet) && invoker.skip_vet) {