aboutsummaryrefslogtreecommitdiff
path: root/go
diff options
context:
space:
mode:
Diffstat (limited to 'go')
-rwxr-xr-xgo/android/adb_shamu8
-rwxr-xr-xgo/android/adb_volantis8
-rwxr-xr-xgo/android/build_go26
-rwxr-xr-xgo/android/go_shamu11
-rwxr-xr-xgo/android/go_shamu_exec8
-rwxr-xr-xgo/android/go_volantis11
-rwxr-xr-xgo/android/go_volantis_exec8
-rwxr-xr-xgo/android/target_cp28
-rwxr-xr-xgo/android/target_sh13
-rwxr-xr-xgo/android/target_tmpdir5
-rwxr-xr-xgo/chromeos/build_go45
-rwxr-xr-xgo/chromeos/go_daisy11
-rwxr-xr-xgo/chromeos/go_daisy_exec10
-rwxr-xr-xgo/chromeos/go_panther11
-rwxr-xr-xgo/chromeos/go_panther_exec10
-rwxr-xr-xgo/chromeos/go_x86-zgb11
-rwxr-xr-xgo/chromeos/go_x86-zgb_exec10
-rwxr-xr-xgo/chromeos/target_cp28
-rwxr-xr-xgo/chromeos/target_sh11
-rwxr-xr-xgo/chromeos/target_tmpdir5
-rwxr-xr-xgo/go_local8
-rwxr-xr-xgo/go_target83
-rwxr-xr-xgo/go_target_exec41
-rw-r--r--go/patch/go0.patch33
-rw-r--r--go/patch/go1.patch50
-rw-r--r--go/patch/go2.patch173
-rw-r--r--go/patch/go3.patch711
-rw-r--r--go/patch/go4.patch101
-rw-r--r--go/patch/go5.patch198
-rw-r--r--go/patch/go6.patch65
-rw-r--r--go/patch/go7.patch139
-rwxr-xr-xgo/push_goroot34
-rwxr-xr-xgo/test_go88
33 files changed, 2002 insertions, 0 deletions
diff --git a/go/android/adb_shamu b/go/android/adb_shamu
new file mode 100755
index 00000000..1c53ecc1
--- /dev/null
+++ b/go/android/adb_shamu
@@ -0,0 +1,8 @@
+#!/bin/bash
+
+# This wrapper runs adb with the serial number of the shamu device.
+# Replace XXXXXXXX with the actual serial number of the device.
+# This is just an example. Create one such wrapper for each Android
+# device used for running Go tests.
+
+exec adb -s XXXXXXXX "$@"
diff --git a/go/android/adb_volantis b/go/android/adb_volantis
new file mode 100755
index 00000000..4712eec2
--- /dev/null
+++ b/go/android/adb_volantis
@@ -0,0 +1,8 @@
+#!/bin/bash
+
+# This wrapper runs adb with the serial number of the volantis device.
+# Replace YYYYYYYY with the actual serial number of the device.
+# This is just an example. Create one such wrapper for each Android
+# device used for running Go tests.
+
+exec adb -s YYYYYYYY "$@"
diff --git a/go/android/build_go b/go/android/build_go
new file mode 100755
index 00000000..65b7ec2b
--- /dev/null
+++ b/go/android/build_go
@@ -0,0 +1,26 @@
+#!/bin/bash
+set -e -o pipefail
+
+# This script builds the go cross compilers for Android targets.
+#
+# Usage: build_go
+#
+# It assumes that the "arm-linux-androideabi" toolchain is already installed.
+# It assumes that the "aarch64-linux-android" toolchain is already installed.
+
+if [[ ! -e "make.bash" && -e "src/make.bash" ]]
+then
+ cd src
+fi
+
+# Build the Go toolchain for arm devices.
+GOOS="android" GOARCH="arm" CGO_ENABLED="1" \
+ CC_FOR_TARGET="arm-linux-androideabi-gcc" \
+ CXX_FOR_TARGET="arm-linux-androideabi-g++" \
+ ./make.bash --no-clean
+
+# Build the Go toolchain for arm64 devices.
+GOOS="android" GOARCH="arm64" CGO_ENABLED="1" \
+ CC_FOR_TARGET="aarch64-linux-android-gcc" \
+ CXX_FOR_TARGET="aarch64-linux-android-g++" \
+ ./make.bash --no-clean
diff --git a/go/android/go_shamu b/go/android/go_shamu
new file mode 100755
index 00000000..7e1ffbea
--- /dev/null
+++ b/go/android/go_shamu
@@ -0,0 +1,11 @@
+#!/bin/bash
+
+# Invoke the Go cross compiler for shamu.
+# Uses ../go_target to add PIE flags.
+#
+# This is just an example for an arm device.
+
+GOOS="android" GOARCH="arm" CGO_ENABLED="1" \
+ CC="arm-linux-androideabi-gcc" \
+ CXX="arm-linux-androideabi-g++" \
+ exec go_target "$@"
diff --git a/go/android/go_shamu_exec b/go/android/go_shamu_exec
new file mode 100755
index 00000000..2c169026
--- /dev/null
+++ b/go/android/go_shamu_exec
@@ -0,0 +1,8 @@
+#!/bin/bash
+
+# Copy and remotely execute a binary on the shamu device.
+#
+# For this to work, the corresponding adb_shamu wrapper
+# must exist to tell adb the serial number of the device.
+
+GOOS="android" GOARCH="arm" exec go_target_exec shamu "$@"
diff --git a/go/android/go_volantis b/go/android/go_volantis
new file mode 100755
index 00000000..bfeab196
--- /dev/null
+++ b/go/android/go_volantis
@@ -0,0 +1,11 @@
+#!/bin/bash
+
+# Invoke the Go cross compiler for volantis.
+# Uses ../go_target to add PIE flags.
+#
+# This is just an example for an arm64 device.
+
+GOOS="android" GOARCH="arm64" CGO_ENABLED="1" \
+ CC="aarch64-linux-android-gcc" \
+ CXX="aarch64-linux-android-g++" \
+ exec go_target "$@"
diff --git a/go/android/go_volantis_exec b/go/android/go_volantis_exec
new file mode 100755
index 00000000..86cb2cfb
--- /dev/null
+++ b/go/android/go_volantis_exec
@@ -0,0 +1,8 @@
+#!/bin/bash
+
+# Copy and remotely execute a binary on the volantis device.
+#
+# For this to work, the corresponding adb_volantis wrapper
+# must exist to tell adb the serial number of the device.
+
+GOOS="android" GOARCH="arm64" exec go_target_exec volantis "$@"
diff --git a/go/android/target_cp b/go/android/target_cp
new file mode 100755
index 00000000..8a311534
--- /dev/null
+++ b/go/android/target_cp
@@ -0,0 +1,28 @@
+#!/bin/bash
+set -e -o pipefail
+
+# Copy a file or directory to the target Android device.
+#
+# Usage: target_cp <src> <target>:<dest>
+
+src="$1"
+shift
+
+targetdest="$1"
+shift
+
+target="${targetdest%:*}"
+dest="${targetdest#*:}"
+
+if [[ -z "${src}" || -z "${target}" || -z "${dest}" || "${targetdest}" != "${target}:${dest}" || -n "$*" ]]
+then
+ echo "Usage: target_cp <src> <target>:<dest>"
+ exit 1
+fi
+
+if [[ -d ${src} ]]
+then
+ adb_${target} push ${src} ${dest}/${src##*/} 2>/dev/null
+else
+ adb_${target} push ${src} ${dest} 2>/dev/null
+fi
diff --git a/go/android/target_sh b/go/android/target_sh
new file mode 100755
index 00000000..241843e8
--- /dev/null
+++ b/go/android/target_sh
@@ -0,0 +1,13 @@
+#!/bin/bash
+set -e -o pipefail
+
+# Run a command on the target Android device.
+#
+# Usage: target_sh <cmd> <args>...
+
+target="$1"
+shift
+
+exitcode="$(target_tmpdir)/exitcode"
+adb_${target} shell "$*; echo -n \$? > ${exitcode}" | sed -e 's:\r$::' -u
+exit $(adb_${target} shell "cat ${exitcode}")
diff --git a/go/android/target_tmpdir b/go/android/target_tmpdir
new file mode 100755
index 00000000..b5953696
--- /dev/null
+++ b/go/android/target_tmpdir
@@ -0,0 +1,5 @@
+#!/bin/bash
+
+# Temporary directory to be used on Android devices.
+
+echo "/data/local/tmp"
diff --git a/go/chromeos/build_go b/go/chromeos/build_go
new file mode 100755
index 00000000..cb882eaf
--- /dev/null
+++ b/go/chromeos/build_go
@@ -0,0 +1,45 @@
+#!/bin/bash
+set -e -o pipefail
+
+# This script builds the go cross compilers for ChromeOS targets.
+#
+# Usage: build_go
+#
+# It assumes that the "x86_64-cros-linux-gnu" toolchain is already installed.
+# It assumes that the "i686-pc-linux-gnu" toolchain is already installed.
+# It assumes that the "armv7a-cros-linux-gnueabi" toolchain is already installed.
+
+if [[ ! -e "make.bash" && -e "src/make.bash" ]]
+then
+ cd src
+fi
+
+# Build the Go toolchain for amd64 targets.
+GOOS="linux" GOARCH="amd64" CGO_ENABLED="1" \
+ CC_FOR_TARGET="x86_64-cros-linux-gnu-gcc" \
+ CXX_FOR_TARGET="x86_64-cros-linux-gnu-g++" \
+ ./make.bash --no-clean
+GOOS="linux" GOARCH="amd64" CGO_ENABLED="1" \
+ CC="x86_64-cros-linux-gnu-gcc" \
+ CXX="x86_64-cros-linux-gnu-g++" \
+ ../bin/go install -v -buildmode=pie std
+
+# Build the Go toolchain for 386 targets.
+GOOS="linux" GOARCH="386" CGO_ENABLED="1" \
+ CC_FOR_TARGET="i686-pc-linux-gnu-gcc" \
+ CXX_FOR_TARGET="i686-pc-linux-gnu-g++" \
+ ./make.bash --no-clean
+GOOS="linux" GOARCH="386" CGO_ENABLED="1" \
+ CC="i686-pc-linux-gnu-gcc" \
+ CXX="i686-pc-linux-gnu-g++" \
+ ../bin/go install -v -buildmode=pie std
+
+# Build the Go toolchain for arm targets.
+GOOS="linux" GOARCH="arm" CGO_ENABLED="1" \
+ CC_FOR_TARGET="armv7a-cros-linux-gnueabi-gcc" \
+ CXX_FOR_TARGET="armv7a-cros-linux-gnueabi-g++" \
+ ./make.bash --no-clean
+GOOS="linux" GOARCH="arm" CGO_ENABLED="1" \
+ CC="armv7a-cros-linux-gnueabi-gcc" \
+ CXX="armv7a-cros-linux-gnueabi-g++" \
+ ../bin/go install -v -buildmode=pie std
diff --git a/go/chromeos/go_daisy b/go/chromeos/go_daisy
new file mode 100755
index 00000000..db4a95ac
--- /dev/null
+++ b/go/chromeos/go_daisy
@@ -0,0 +1,11 @@
+#!/bin/bash
+
+# Invoke the Go cross compiler for daisy.
+# Uses ../go_target to add PIE flags.
+#
+# This is just an example for an arm board.
+
+GOOS="linux" GOARCH="arm" CGO_ENABLED="1" \
+ CC="armv7a-cros-linux-gnueabi-gcc" \
+ CXX="armv7a-cros-linux-gnueabi-g++" \
+ exec go_target "$@"
diff --git a/go/chromeos/go_daisy_exec b/go/chromeos/go_daisy_exec
new file mode 100755
index 00000000..3b9a63dd
--- /dev/null
+++ b/go/chromeos/go_daisy_exec
@@ -0,0 +1,10 @@
+#!/bin/bash
+
+# Copy and remotely execute a binary on the daisy device.
+#
+# For this to work, the corresponding entry must exist in
+# ~/.ssh/config and the device must already be setup for
+# password-less authentication. See setup instructions at
+# http://go/chromeos-toolchain-team/go-toolchain
+
+GOOS="linux" GOARCH="arm" exec go_target_exec daisy "$@"
diff --git a/go/chromeos/go_panther b/go/chromeos/go_panther
new file mode 100755
index 00000000..5c06f432
--- /dev/null
+++ b/go/chromeos/go_panther
@@ -0,0 +1,11 @@
+#!/bin/bash
+
+# Invoke the Go cross compiler for panther.
+# Uses ../go_target to add PIE flags.
+#
+# This is just an example for an amd64 board.
+
+GOOS="linux" GOARCH="amd64" CGO_ENABLED="1" \
+ CC="x86_64-cros-linux-gnu-gcc" \
+ CXX="x86_64-cros-linux-gnu-g++" \
+ exec go_target "$@"
diff --git a/go/chromeos/go_panther_exec b/go/chromeos/go_panther_exec
new file mode 100755
index 00000000..64f77b1f
--- /dev/null
+++ b/go/chromeos/go_panther_exec
@@ -0,0 +1,10 @@
+#!/bin/bash
+
+# Copy and remotely execute a binary on the panther device.
+#
+# For this to work, the corresponding entry must exist in
+# ~/.ssh/config and the device must already be setup for
+# password-less authentication. See setup instructions at
+# http://go/chromeos-toolchain-team/go-toolchain
+
+GOOS="linux" GOARCH="amd64" exec go_target_exec panther "$@"
diff --git a/go/chromeos/go_x86-zgb b/go/chromeos/go_x86-zgb
new file mode 100755
index 00000000..272efb58
--- /dev/null
+++ b/go/chromeos/go_x86-zgb
@@ -0,0 +1,11 @@
+#!/bin/bash
+
+# Invoke the Go cross compiler for x86-zgb.
+# Uses ../go_target to add PIE flags.
+#
+# This is just an example for an 386 board.
+
+GOOS="linux" GOARCH="386" CGO_ENABLED="1" \
+ CC="i686-pc-linux-gnu-gcc" \
+ CXX="i686-pc-linux-gnu-g++" \
+ exec go_target "$@"
diff --git a/go/chromeos/go_x86-zgb_exec b/go/chromeos/go_x86-zgb_exec
new file mode 100755
index 00000000..b0341f21
--- /dev/null
+++ b/go/chromeos/go_x86-zgb_exec
@@ -0,0 +1,10 @@
+#!/bin/bash
+
+# Copy and remotely execute a binary on the x86-zgb device.
+#
+# For this to work, the corresponding entry must exist in
+# ~/.ssh/config and the device must already be setup for
+# password-less authentication. See setup instructions at
+# http://go/chromeos-toolchain-team/go-toolchain
+
+GOOS="linux" GOARCH="386" exec go_target_exec x86-zgb "$@"
diff --git a/go/chromeos/target_cp b/go/chromeos/target_cp
new file mode 100755
index 00000000..6df476e6
--- /dev/null
+++ b/go/chromeos/target_cp
@@ -0,0 +1,28 @@
+#!/bin/bash
+set -e -o pipefail
+
+# Copy a file or directory to the target ChromeOS device.
+#
+# Usage: target_cp <src> <target>:<dest>
+
+src="$1"
+shift
+
+targetdest="$1"
+shift
+
+target="${targetdest%:*}"
+dest="${targetdest#*:}"
+
+if [[ -z "${src}" || -z "${target}" || -z "${dest}" || "${targetdest}" != "${target}:${dest}" || -n "$*" ]]
+then
+ echo "Usage: target_cp <src> <target>:<dest>"
+ exit 1
+fi
+
+if [[ -d ${src} ]]
+then
+ scp -rq ${src} ${target}:${dest}
+else
+ scp -q ${src} ${target}:${dest}
+fi
diff --git a/go/chromeos/target_sh b/go/chromeos/target_sh
new file mode 100755
index 00000000..43c5fac6
--- /dev/null
+++ b/go/chromeos/target_sh
@@ -0,0 +1,11 @@
+#!/bin/bash
+set -e -o pipefail
+
+# Run a command on the target ChromeOS device.
+#
+# Usage: target_sh <cmd> <args>...
+
+target="$1"
+shift
+
+ssh ${target} "$*"
diff --git a/go/chromeos/target_tmpdir b/go/chromeos/target_tmpdir
new file mode 100755
index 00000000..382a0334
--- /dev/null
+++ b/go/chromeos/target_tmpdir
@@ -0,0 +1,5 @@
+#!/bin/bash
+
+# Temporary directory to be used on ChromeOS devices.
+
+echo "/tmp"
diff --git a/go/go_local b/go/go_local
new file mode 100755
index 00000000..92954ef8
--- /dev/null
+++ b/go/go_local
@@ -0,0 +1,8 @@
+#!/bin/bash
+
+# Invoke the Go compiler for localhost.
+
+GOOS="linux" GOARCH="amd64" CGO_ENABLED="1" \
+ CC="gcc" \
+ CXX="g++" \
+ exec go "$@"
diff --git a/go/go_target b/go/go_target
new file mode 100755
index 00000000..05786377
--- /dev/null
+++ b/go/go_target
@@ -0,0 +1,83 @@
+#!/bin/bash
+set -e -o pipefail
+
+# This script wraps the go cross compilers.
+#
+# It ensures that Go binaries are linked with an external linker
+# by default (cross gcc). Appropriate flags are added to build a
+# position independent executable (PIE) for ASLR.
+# "export GOPIE=0" to temporarily disable this behavior.
+
+function pie_enabled()
+ {
+ [[ "${GOPIE}" != "0" ]]
+ }
+
+function has_ldflags()
+ {
+ # Check if any linker flags are present in argv.
+ for arg in "$@"
+ do
+ case "${arg}" in
+ -ldflags | -ldflags=*) return 0 ;;
+ -linkmode | -linkmode=*) return 0 ;;
+ -buildmode | -buildmode=*) return 0 ;;
+ -installsuffix | -installsuffix=*) return 0 ;;
+ -extld | -extld=*) return 0 ;;
+ -extldflags | -extldflags=*) return 0 ;;
+ esac
+ done
+ return 1
+ }
+
+pie_flags=()
+if pie_enabled && ! has_ldflags "$@"
+then
+ case "$1" in
+ build | install | run | test)
+ # Add "-buildmode=pie" to "go build|install|run|test" commands.
+ pie_flags=(
+ "$1"
+ "-buildmode=pie"
+ )
+ shift
+ ;;
+ tool)
+ case "$2" in
+ asm)
+ # Handle direct assembler invocations ("go tool asm <args>").
+ pie_flags=(
+ "$1"
+ "$2"
+ "-shared"
+ )
+ shift 2
+ ;;
+ compile)
+ # Handle direct compiler invocations ("go tool compile <args>").
+ pie_flags=(
+ "$1"
+ "$2"
+ "-shared"
+ "-installsuffix=shared"
+ )
+ shift 2
+ ;;
+ link)
+ # Handle direct linker invocations ("go tool link <args>").
+ pie_flags=(
+ "$1"
+ "$2"
+ "-installsuffix=shared"
+ "-buildmode=pie"
+ "-extld"
+ "${CC}"
+ )
+ shift 2
+ ;;
+ esac
+ ;;
+ esac
+fi
+
+exec go "${pie_flags[@]}" "$@"
diff --git a/go/go_target_exec b/go/go_target_exec
new file mode 100755
index 00000000..34d9e799
--- /dev/null
+++ b/go/go_target_exec
@@ -0,0 +1,41 @@
+#!/bin/bash
+set -e -o pipefail
+
+# This wrapper copies an executable to a target device and executes it there.
+#
+# Usage: go_target_exec <target> <binary> <args>...
+#
+# This script can work with both ChromeOS/Android devices.
+#
+# It uses "target_tmpdir" to get the path to the temporary directory on the device.
+# It uses "target_cp" to copy the binary to the temporary directory on the device.
+# It uses "target_sh" to execute the binary remotely and get the output/exitcode.
+
+target="$1"
+shift
+
+binary="$1"
+shift
+
+# Get path to temporary directory on device and copy the binary over.
+tmpdir="$(target_tmpdir)"
+target_cp ${binary} ${target}:${tmpdir}/a.out
+
+# If current directory is inside GOROOT, then execute the binary in the
+# corresponding directory inside GOROOT on the device.
+targetdir="${tmpdir}"
+goroot="$(go_${target} env GOROOT)"
+if [[ "${PWD}" == ${goroot}/src/* ]]
+then
+ targetdir="${tmpdir}/go/src/${PWD#${goroot}/src/}"
+fi
+
+# Set GOROOT, and forward some environment variables to the remote shell.
+vars="GOROOT=${tmpdir}/go"
+vars+="${GOOS:+ GOOS=${GOOS}}"
+vars+="${GOARCH:+ GOARCH=${GOARCH}}"
+vars+="${GOMAXPROCS:+ GOMAXPROCS=${GOMAXPROCS}}"
+vars+="${GOTRACEBACK:+ GOTRACEBACK=${GOTRACEBACK}}"
+
+# Remotely execute the binary using ssh (for ChromeOS) or adb (for Android).
+target_sh ${target} "cd ${targetdir} && ${vars} ${tmpdir}/a.out $*"
diff --git a/go/patch/go0.patch b/go/patch/go0.patch
new file mode 100644
index 00000000..27e1451e
--- /dev/null
+++ b/go/patch/go0.patch
@@ -0,0 +1,33 @@
+testenv: look for "go" executable in path.
+
+--- src/go/build/deps_test.go
++++ src/go/build/deps_test.go
+@@ -168,7 +168,7 @@ var pkgDeps = map[string][]string{
+ "testing": {"L2", "flag", "fmt", "os", "runtime/debug", "runtime/pprof", "runtime/trace", "time"},
+ "testing/iotest": {"L2", "log"},
+ "testing/quick": {"L2", "flag", "fmt", "reflect"},
+- "internal/testenv": {"L2", "os", "testing"},
++ "internal/testenv": {"L2", "os", "os/exec", "testing"},
+
+ // L4 is defined as L3+fmt+log+time, because in general once
+ // you're using L3 packages, use of fmt, log, or time is not a big deal.
+--- src/internal/testenv/testenv.go
++++ src/internal/testenv/testenv.go
+@@ -12,6 +12,7 @@ package testenv
+
+ import (
+ "os"
++ "os/exec"
+ "runtime"
+ "strings"
+ "testing"
+@@ -36,6 +37,9 @@ func HasGoBuild() bool {
+ return false
+ }
+ }
++ if _, err := exec.LookPath("go"); err != nil {
++ return false
++ }
+ return true
+ }
+
diff --git a/go/patch/go1.patch b/go/patch/go1.patch
new file mode 100644
index 00000000..49d229ec
--- /dev/null
+++ b/go/patch/go1.patch
@@ -0,0 +1,50 @@
+test: enable some tests on android/arm64.
+
+--- test/chanlinear.go
++++ test/chanlinear.go
+@@ -1,4 +1,4 @@
+-// +build darwin linux
++// +build darwin linux android
+ // run
+
+ // Copyright 2014 The Go Authors. All rights reserved.
+--- test/fixedbugs/bug385_64.go
++++ test/fixedbugs/bug385_64.go
+@@ -1,4 +1,4 @@
+-// +build amd64
++// +build amd64 arm64
+ // errorcheck
+
+ // Copyright 2011 The Go Authors. All rights reserved.
+--- test/fixedbugs/issue10607.go
++++ test/fixedbugs/issue10607.go
+@@ -1,4 +1,4 @@
+-// +build linux,!ppc64,!ppc64le,!mips64,!mips64le
++// +build linux,!ppc64,!ppc64le,!mips64,!mips64le android
+ // run
+
+ // Copyright 2015 The Go Authors. All rights reserved.
+--- test/fixedbugs/issue6036.go
++++ test/fixedbugs/issue6036.go
+@@ -1,4 +1,4 @@
+-// +build amd64
++// +build amd64 arm64
+ // compile
+
+ // Copyright 2013 The Go Authors. All rights reserved.
+--- test/maplinear.go
++++ test/maplinear.go
+@@ -1,4 +1,4 @@
+-// +build darwin linux
++// +build darwin linux android
+ // run
+
+ // Copyright 2013 The Go Authors. All rights reserved.
+--- test/recover4.go
++++ test/recover4.go
+@@ -1,4 +1,4 @@
+-// +build linux darwin
++// +build linux android darwin
+ // run
+
+ // Copyright 2015 The Go Authors. All rights reserved.
diff --git a/go/patch/go2.patch b/go/patch/go2.patch
new file mode 100644
index 00000000..dfc236a4
--- /dev/null
+++ b/go/patch/go2.patch
@@ -0,0 +1,173 @@
+test: add -target flag.
+
+--- test/run.go
++++ test/run.go
+@@ -37,9 +37,9 @@ var (
+ numParallel = flag.Int("n", runtime.NumCPU(), "number of parallel tests to run")
+ summary = flag.Bool("summary", false, "show summary of results")
+ showSkips = flag.Bool("show_skips", false, "show skipped tests")
+- linkshared = flag.Bool("linkshared", false, "")
+ updateErrors = flag.Bool("update_errors", false, "update error messages in test file based on compiler output")
+ runoutputLimit = flag.Int("l", defaultRunOutputLimit(), "number of parallel runoutput tests to run")
++ target = flag.String("target", "", "if non empty, use 'go_target' to compile test files and 'go_target_exec' to run the binaries")
+
+ shard = flag.Int("shard", 0, "shard index to run. Only applicable if -shards is non-zero.")
+ shards = flag.Int("shards", 0, "number of shards. If 0, all tests are run. This is used by the continuous build.")
+@@ -192,19 +192,11 @@ func goFiles(dir string) []string {
+ type runCmd func(...string) ([]byte, error)
+
+ func compileFile(runcmd runCmd, longname string) (out []byte, err error) {
+- cmd := []string{"go", "tool", "compile", "-e"}
+- if *linkshared {
+- cmd = append(cmd, "-dynlink", "-installsuffix=dynlink")
+- }
+- cmd = append(cmd, longname)
+- return runcmd(cmd...)
++ return runcmd(findGoCmd(), "tool", "compile", "-e", longname)
+ }
+
+ func compileInDir(runcmd runCmd, dir string, names ...string) (out []byte, err error) {
+- cmd := []string{"go", "tool", "compile", "-e", "-D", ".", "-I", "."}
+- if *linkshared {
+- cmd = append(cmd, "-dynlink", "-installsuffix=dynlink")
+- }
++ cmd := []string{findGoCmd(), "tool", "compile", "-e", "-D", ".", "-I", "."}
+ for _, name := range names {
+ cmd = append(cmd, filepath.Join(dir, name))
+ }
+@@ -213,15 +205,21 @@ func compileInDir(runcmd runCmd, dir string, names ...string) (out []byte, err e
+
+ func linkFile(runcmd runCmd, goname string) (err error) {
+ pfile := strings.Replace(goname, ".go", ".o", -1)
+- cmd := []string{"go", "tool", "link", "-w", "-o", "a.exe", "-L", "."}
+- if *linkshared {
+- cmd = append(cmd, "-linkshared", "-installsuffix=dynlink")
+- }
+- cmd = append(cmd, pfile)
+- _, err = runcmd(cmd...)
++ _, err = runcmd(findGoCmd(), "tool", "link", "-w", "-o", "a.exe", "-L", ".", pfile)
+ return
+ }
+
++func goRun(runcmd runCmd, goname string, args ...string) (out []byte, err error) {
++ cmd := []string{findGoCmd(), "run"}
++ if len(findExecCmd()) > 0 {
++ cmd = append(cmd, "-exec")
++ cmd = append(cmd, findExecCmd()...)
++ }
++ cmd = append(cmd, goname)
++ cmd = append(cmd, args...)
++ return runcmd(cmd...)
++}
++
+ // skipError describes why a test was skipped.
+ type skipError string
+
+@@ -530,8 +528,7 @@ func (t *test) run() {
+ t.err = fmt.Errorf("unimplemented action %q", action)
+
+ case "errorcheck":
+- cmdline := []string{"go", "tool", "compile", "-e", "-o", "a.o"}
+- // No need to add -dynlink even if linkshared if we're just checking for errors...
++ cmdline := []string{findGoCmd(), "tool", "compile", "-e", "-o", "a.o"}
+ cmdline = append(cmdline, flags...)
+ cmdline = append(cmdline, long)
+ out, err := runcmd(cmdline...)
+@@ -640,19 +637,14 @@ func (t *test) run() {
+ }
+
+ case "build":
+- _, err := runcmd("go", "build", "-o", "a.exe", long)
++ _, err := runcmd(findGoCmd(), "build", "-o", "a.exe", long)
+ if err != nil {
+ t.err = err
+ }
+
+ case "run":
+ useTmp = false
+- cmd := []string{"go", "run"}
+- if *linkshared {
+- cmd = append(cmd, "-linkshared")
+- }
+- cmd = append(cmd, t.goFileName())
+- out, err := runcmd(append(cmd, args...)...)
++ out, err := goRun(runcmd, t.goFileName(), args...)
+ if err != nil {
+ t.err = err
+ return
+@@ -667,12 +659,7 @@ func (t *test) run() {
+ <-rungatec
+ }()
+ useTmp = false
+- cmd := []string{"go", "run"}
+- if *linkshared {
+- cmd = append(cmd, "-linkshared")
+- }
+- cmd = append(cmd, t.goFileName())
+- out, err := runcmd(append(cmd, args...)...)
++ out, err := goRun(runcmd, t.goFileName(), args...)
+ if err != nil {
+ t.err = err
+ return
+@@ -682,12 +669,7 @@ func (t *test) run() {
+ t.err = fmt.Errorf("write tempfile:%s", err)
+ return
+ }
+- cmd = []string{"go", "run"}
+- if *linkshared {
+- cmd = append(cmd, "-linkshared")
+- }
+- cmd = append(cmd, tfile)
+- out, err = runcmd(cmd...)
++ out, err = goRun(runcmd, tfile)
+ if err != nil {
+ t.err = err
+ return
+@@ -698,12 +680,7 @@ func (t *test) run() {
+
+ case "errorcheckoutput":
+ useTmp = false
+- cmd := []string{"go", "run"}
+- if *linkshared {
+- cmd = append(cmd, "-linkshared")
+- }
+- cmd = append(cmd, t.goFileName())
+- out, err := runcmd(append(cmd, args...)...)
++ out, err := goRun(runcmd, t.goFileName(), args...)
+ if err != nil {
+ t.err = err
+ return
+@@ -714,7 +691,7 @@ func (t *test) run() {
+ t.err = fmt.Errorf("write tempfile:%s", err)
+ return
+ }
+- cmdline := []string{"go", "tool", "compile", "-e", "-o", "a.o"}
++ cmdline := []string{findGoCmd(), "tool", "compile", "-e", "-o", "a.o"}
+ cmdline = append(cmdline, flags...)
+ cmdline = append(cmdline, tfile)
+ out, err = runcmd(cmdline...)
+@@ -741,6 +718,10 @@ func findExecCmd() []string {
+ return execCmd
+ }
+ execCmd = []string{} // avoid work the second time
++ if *target != "" {
++ execCmd = []string{"go_" + *target + "_exec"}
++ return execCmd
++ }
+ if goos == runtime.GOOS && goarch == runtime.GOARCH {
+ return execCmd
+ }
+@@ -751,6 +732,13 @@ func findExecCmd() []string {
+ return execCmd
+ }
+
++func findGoCmd() string {
++ if *target != "" {
++ return "go_" + *target
++ }
++ return "go"
++}
++
+ func (t *test) String() string {
+ return filepath.Join(t.dir, t.gofile)
+ }
diff --git a/go/patch/go3.patch b/go/patch/go3.patch
new file mode 100644
index 00000000..37bd562f
--- /dev/null
+++ b/go/patch/go3.patch
@@ -0,0 +1,711 @@
+test: add runtarget action.
+
+--- test/fixedbugs/bug248.go
++++ test/fixedbugs/bug248.go
+@@ -1,5 +1,5 @@
+ // +build !nacl,!plan9,!windows
+-// run
++// runtarget
+
+ // Copyright 2009 The Go Authors. All rights reserved.
+ // Use of this source code is governed by a BSD-style
+@@ -8,13 +8,32 @@
+ package main
+
+ import (
++ "flag"
+ "fmt"
+ "os"
+ "os/exec"
+ "path/filepath"
+ )
+
++var target = flag.String("target", "", "if non empty, use 'go_target' to compile test files and 'go_target_exec' to run the binaries")
++
++func goCmd() string {
++ if *target != "" {
++ return "go_" + *target
++ }
++ return "go"
++}
++
++func goRun(cmd ...string) {
++ if *target == "" {
++ run(cmd[0], cmd[1:]...)
++ } else {
++ run("go_"+*target+"_exec", cmd...)
++ }
++}
++
+ func main() {
++ flag.Parse()
+ // TODO: If we get rid of errchk, re-enable this test on Windows.
+ errchk, err := filepath.Abs("errchk")
+ check(err)
+@@ -22,12 +41,12 @@ func main() {
+ err = os.Chdir(filepath.Join("fixedbugs", "bug248.dir"))
+ check(err)
+
+- run("go", "tool", "compile", "bug0.go")
+- run("go", "tool", "compile", "bug1.go")
+- run("go", "tool", "compile", "bug2.go")
+- run(errchk, "go", "tool", "compile", "-e", "bug3.go")
+- run("go", "tool", "link", "bug2.o")
+- run(fmt.Sprintf(".%ca.out", filepath.Separator))
++ run(goCmd(), "tool", "compile", "bug0.go")
++ run(goCmd(), "tool", "compile", "bug1.go")
++ run(goCmd(), "tool", "compile", "bug2.go")
++ run(errchk, goCmd(), "tool", "compile", "-e", "bug3.go")
++ run(goCmd(), "tool", "link", "bug2.o")
++ goRun(fmt.Sprintf(".%ca.out", filepath.Separator))
+
+ os.Remove("bug0.o")
+ os.Remove("bug1.o")
+--- test/fixedbugs/bug302.go
++++ test/fixedbugs/bug302.go
+@@ -1,5 +1,5 @@
+ // +build !nacl
+-// run
++// runtarget
+
+ // Copyright 2010 The Go Authors. All rights reserved.
+ // Use of this source code is governed by a BSD-style
+@@ -8,16 +8,27 @@
+ package main
+
+ import (
++ "flag"
+ "fmt"
+ "os"
+ "os/exec"
+ "path/filepath"
+ )
+
++var target = flag.String("target", "", "if non empty, use 'go_target' to compile test files and 'go_target_exec' to run the binaries")
++
++func goCmd() string {
++ if *target != "" {
++ return "go_" + *target
++ }
++ return "go"
++}
++
+ func main() {
+- run("go", "tool", "compile", filepath.Join("fixedbugs", "bug302.dir", "p.go"))
+- run("go", "tool", "pack", "grc", "pp.a", "p.o")
+- run("go", "tool", "compile", "-I", ".", filepath.Join("fixedbugs", "bug302.dir", "main.go"))
++ flag.Parse()
++ run(goCmd(), "tool", "compile", filepath.Join("fixedbugs", "bug302.dir", "p.go"))
++ run(goCmd(), "tool", "pack", "grc", "pp.a", "p.o")
++ run(goCmd(), "tool", "compile", "-I", ".", filepath.Join("fixedbugs", "bug302.dir", "main.go"))
+ os.Remove("p.o")
+ os.Remove("pp.a")
+ os.Remove("main.o")
+--- test/fixedbugs/bug345.go
++++ test/fixedbugs/bug345.go
+@@ -1,5 +1,5 @@
+ // +build !nacl,!plan9,!windows
+-// run
++// runtarget
+
+ // Copyright 2011 The Go Authors. All rights reserved.
+ // Use of this source code is governed by a BSD-style
+@@ -8,13 +8,24 @@
+ package main
+
+ import (
++ "flag"
+ "fmt"
+ "os"
+ "os/exec"
+ "path/filepath"
+ )
+
++var target = flag.String("target", "", "if non empty, use 'go_target' to compile test files and 'go_target_exec' to run the binaries")
++
++func goCmd() string {
++ if *target != "" {
++ return "go_" + *target
++ }
++ return "go"
++}
++
+ func main() {
++ flag.Parse()
+ // TODO: If we get rid of errchk, re-enable this test on Plan 9 and Windows.
+ errchk, err := filepath.Abs("errchk")
+ check(err)
+@@ -22,8 +33,8 @@ func main() {
+ err = os.Chdir(filepath.Join(".", "fixedbugs", "bug345.dir"))
+ check(err)
+
+- run("go", "tool", "compile", "io.go")
+- run(errchk, "go", "tool", "compile", "-e", "main.go")
++ run(goCmd(), "tool", "compile", "io.go")
++ run(errchk, goCmd(), "tool", "compile", "-e", "main.go")
+ os.Remove("io.o")
+ }
+
+--- test/fixedbugs/bug369.go
++++ test/fixedbugs/bug369.go
+@@ -1,5 +1,5 @@
+ // +build !nacl,!windows
+-// run
++// runtarget
+
+ // Copyright 2011 The Go Authors. All rights reserved.
+ // Use of this source code is governed by a BSD-style
+@@ -10,21 +10,40 @@
+ package main
+
+ import (
++ "flag"
+ "fmt"
+ "os"
+ "os/exec"
+ "path/filepath"
+ )
+
++var target = flag.String("target", "", "if non empty, use 'go_target' to compile test files and 'go_target_exec' to run the binaries")
++
++func goCmd() string {
++ if *target != "" {
++ return "go_" + *target
++ }
++ return "go"
++}
++
++func goRun(cmd ...string) {
++ if *target == "" {
++ run(cmd[0], cmd[1:]...)
++ } else {
++ run("go_"+*target+"_exec", cmd...)
++ }
++}
++
+ func main() {
++ flag.Parse()
+ err := os.Chdir(filepath.Join(".", "fixedbugs", "bug369.dir"))
+ check(err)
+
+- run("go", "tool", "compile", "-N", "-o", "slow.o", "pkg.go")
+- run("go", "tool", "compile", "-o", "fast.o", "pkg.go")
+- run("go", "tool", "compile", "-o", "main.o", "main.go")
+- run("go", "tool", "link", "-o", "a.exe", "main.o")
+- run("." + string(filepath.Separator) + "a.exe")
++ run(goCmd(), "tool", "compile", "-N", "-o", "slow.o", "pkg.go")
++ run(goCmd(), "tool", "compile", "-o", "fast.o", "pkg.go")
++ run(goCmd(), "tool", "compile", "-o", "main.o", "main.go")
++ run(goCmd(), "tool", "link", "-o", "a.exe", "main.o")
++ goRun("." + string(filepath.Separator) + "a.exe")
+
+ os.Remove("slow.o")
+ os.Remove("fast.o")
+--- test/fixedbugs/bug429_run.go
++++ test/fixedbugs/bug429_run.go
+@@ -1,5 +1,5 @@
+ // +build !nacl
+-// run
++// runtarget
+
+ // Copyright 2014 The Go Authors. All rights reserved.
+ // Use of this source code is governed by a BSD-style
+@@ -10,6 +10,7 @@
+ package main
+
+ import (
++ "flag"
+ "fmt"
+ "os"
+ "os/exec"
+@@ -17,8 +18,27 @@ import (
+ "strings"
+ )
+
++var target = flag.String("target", "", "if non empty, use 'go_target' to compile test files and 'go_target_exec' to run the binaries")
++
++func goCmd() string {
++ if *target != "" {
++ return "go_" + *target
++ }
++ return "go"
++}
++
++func goRun(args ...string) *exec.Cmd {
++ cmd := []string{"run"}
++ if *target != "" {
++ cmd = append(cmd, "-exec", "go_"+*target+"_exec")
++ }
++ cmd = append(cmd, args...)
++ return exec.Command(goCmd(), cmd...)
++}
++
+ func main() {
+- cmd := exec.Command("go", "run", filepath.Join("fixedbugs", "bug429.go"))
++ flag.Parse()
++ cmd := goRun(filepath.Join("fixedbugs", "bug429.go"))
+ out, err := cmd.CombinedOutput()
+ if err == nil {
+ fmt.Println("expected deadlock")
+--- test/fixedbugs/issue10607.go
++++ test/fixedbugs/issue10607.go
+@@ -1,5 +1,5 @@
+ // +build linux,!ppc64,!ppc64le,!mips64,!mips64le android
+-// run
++// runtarget
+
+ // Copyright 2015 The Go Authors. All rights reserved.
+ // Use of this source code is governed by a BSD-style
+@@ -11,19 +11,39 @@
+ package main
+
+ import (
++ "flag"
+ "fmt"
+ "os"
+ "os/exec"
+ "path/filepath"
+ )
+
++var target = flag.String("target", "", "if non empty, use 'go_target' to compile test files and 'go_target_exec' to run the binaries")
++
++func goCmd() string {
++ if *target != "" {
++ return "go_" + *target
++ }
++ return "go"
++}
++
++func goRun(args ...string) *exec.Cmd {
++ cmd := []string{"run"}
++ if *target != "" {
++ cmd = append(cmd, "-exec", "go_"+*target+"_exec")
++ }
++ cmd = append(cmd, args...)
++ return exec.Command(goCmd(), cmd...)
++}
++
+ func main() {
++ flag.Parse()
+ test("internal")
+ test("external")
+ }
+
+ func test(linkmode string) {
+- out, err := exec.Command("go", "run", "-ldflags", "-B=0x12345678 -linkmode="+linkmode, filepath.Join("fixedbugs", "issue10607a.go")).CombinedOutput()
++ out, err := goRun("-ldflags", "-B=0x12345678 -linkmode="+linkmode, filepath.Join("fixedbugs", "issue10607a.go")).CombinedOutput()
+ if err != nil {
+ fmt.Printf("BUG: linkmode=%s %v\n%s\n", linkmode, err, out)
+ os.Exit(1)
+--- test/fixedbugs/issue11771.go
++++ test/fixedbugs/issue11771.go
+@@ -1,5 +1,5 @@
+ // +build !nacl
+-// run
++// runtarget
+
+ // Copyright 2015 The Go Authors. All rights reserved.
+ // Use of this source code is governed by a BSD-style
+@@ -11,6 +11,7 @@ package main
+
+ import (
+ "bytes"
++ "flag"
+ "fmt"
+ "io/ioutil"
+ "log"
+@@ -20,7 +21,17 @@ import (
+ "runtime"
+ )
+
++var target = flag.String("target", "", "if non empty, use 'go_target' to compile test files and 'go_target_exec' to run the binaries")
++
++func goCmd() string {
++ if *target != "" {
++ return "go_" + *target
++ }
++ return "go"
++}
++
+ func main() {
++ flag.Parse()
+ if runtime.Compiler != "gc" {
+ return
+ }
+@@ -52,7 +63,7 @@ func x() {
+ log.Fatal(err)
+ }
+
+- cmd := exec.Command("go", "tool", "compile", "x.go")
++ cmd := exec.Command(goCmd(), "tool", "compile", "x.go")
+ cmd.Dir = dir
+ output, err := cmd.CombinedOutput()
+ if err == nil {
+--- test/fixedbugs/issue9355.go
++++ test/fixedbugs/issue9355.go
+@@ -1,4 +1,4 @@
+-// run
++// runtarget
+
+ // Copyright 2014 The Go Authors. All rights reserved.
+ // Use of this source code is governed by a BSD-style
+@@ -7,6 +7,7 @@
+ package main
+
+ import (
++ "flag"
+ "fmt"
+ "os"
+ "os/exec"
+@@ -15,7 +16,17 @@ import (
+ "runtime"
+ )
+
++var target = flag.String("target", "", "if non empty, use 'go_target' to compile test files and 'go_target_exec' to run the binaries")
++
++func goCmd() string {
++ if *target != "" {
++ return "go_" + *target
++ }
++ return "go"
++}
++
+ func main() {
++ flag.Parse()
+ if runtime.Compiler != "gc" || runtime.GOOS == "nacl" {
+ return
+ }
+@@ -23,7 +34,7 @@ func main() {
+ err := os.Chdir(filepath.Join("fixedbugs", "issue9355.dir"))
+ check(err)
+
+- out := run("go", "tool", "compile", "-S", "a.go")
++ out := run(goCmd(), "tool", "compile", "-S", "a.go")
+ os.Remove("a.o")
+
+ // 6g/8g print the offset as dec, but 5g/9g print the offset as hex.
+--- test/fixedbugs/issue9862_run.go
++++ test/fixedbugs/issue9862_run.go
+@@ -1,5 +1,5 @@
+ // +build !nacl
+-// run
++// runtarget
+
+ // Copyright 2015 The Go Authors. All rights reserved.
+ // Use of this source code is governed by a BSD-style
+@@ -10,12 +10,32 @@
+ package main
+
+ import (
++ "flag"
+ "os/exec"
+ "strings"
+ )
+
++var target = flag.String("target", "", "if non empty, use 'go_target' to compile test files and 'go_target_exec' to run the binaries")
++
++func goCmd() string {
++ if *target != "" {
++ return "go_" + *target
++ }
++ return "go"
++}
++
++func goRun(args ...string) *exec.Cmd {
++ cmd := []string{"run"}
++ if *target != "" {
++ cmd = append(cmd, "-exec", "go_"+*target+"_exec")
++ }
++ cmd = append(cmd, args...)
++ return exec.Command(goCmd(), cmd...)
++}
++
+ func main() {
+- out, err := exec.Command("go", "run", "fixedbugs/issue9862.go").CombinedOutput()
++ flag.Parse()
++ out, err := goRun("fixedbugs/issue9862.go").CombinedOutput()
+ outstr := string(out)
+ if err == nil {
+ println("go run issue9862.go succeeded, should have failed\n", outstr)
+--- test/linkmain_run.go
++++ test/linkmain_run.go
+@@ -1,5 +1,5 @@
+ // +build !nacl
+-// run
++// runtarget
+
+ // Copyright 2014 The Go Authors. All rights reserved.
+ // Use of this source code is governed by a BSD-style
+@@ -10,12 +10,22 @@
+ package main
+
+ import (
++ "flag"
+ "fmt"
+ "os"
+ "os/exec"
+ "strings"
+ )
+
++var target = flag.String("target", "", "if non empty, use 'go_target' to compile test files and 'go_target_exec' to run the binaries")
++
++func goCmd() string {
++ if *target != "" {
++ return "go_" + *target
++ }
++ return "go"
++}
++
+ func cleanup() {
+ os.Remove("linkmain.o")
+ os.Remove("linkmain.a")
+@@ -51,16 +61,18 @@ func runFail(cmdline string) {
+ }
+
+ func main() {
++ flag.Parse()
++
+ // helloworld.go is package main
+- run("go tool compile -o linkmain.o helloworld.go")
+- run("go tool compile -pack -o linkmain.a helloworld.go")
+- run("go tool link -o linkmain.exe linkmain.o")
+- run("go tool link -o linkmain.exe linkmain.a")
++ run(goCmd() + " tool compile -o linkmain.o helloworld.go")
++ run(goCmd() + " tool compile -pack -o linkmain.a helloworld.go")
++ run(goCmd() + " tool link -o linkmain.exe linkmain.o")
++ run(goCmd() + " tool link -o linkmain.exe linkmain.a")
+
+ // linkmain.go is not
+- run("go tool compile -o linkmain1.o linkmain.go")
+- run("go tool compile -pack -o linkmain1.a linkmain.go")
+- runFail("go tool link -o linkmain.exe linkmain1.o")
+- runFail("go tool link -o linkmain.exe linkmain1.a")
++ run(goCmd() + " tool compile -o linkmain1.o linkmain.go")
++ run(goCmd() + " tool compile -pack -o linkmain1.a linkmain.go")
++ runFail(goCmd() + " tool link -o linkmain.exe linkmain1.o")
++ runFail(goCmd() + " tool link -o linkmain.exe linkmain1.a")
+ cleanup()
+ }
+--- test/linkx_run.go
++++ test/linkx_run.go
+@@ -1,5 +1,5 @@
+ // +build !nacl
+-// run
++// runtarget
+
+ // Copyright 2014 The Go Authors. All rights reserved.
+ // Use of this source code is governed by a BSD-style
+@@ -11,20 +11,40 @@ package main
+
+ import (
+ "bytes"
++ "flag"
+ "fmt"
+ "os"
+ "os/exec"
+ "strings"
+ )
+
++var target = flag.String("target", "", "if non empty, use 'go_target' to compile test files and 'go_target_exec' to run the binaries")
++
++func goCmd() string {
++ if *target != "" {
++ return "go_" + *target
++ }
++ return "go"
++}
++
++func goRun(args ...string) *exec.Cmd {
++ cmd := []string{"run"}
++ if *target != "" {
++ cmd = append(cmd, "-exec", "go_"+*target+"_exec")
++ }
++ cmd = append(cmd, args...)
++ return exec.Command(goCmd(), cmd...)
++}
++
+ func main() {
++ flag.Parse()
+ test(" ") // old deprecated syntax
+ test("=") // new syntax
+ }
+
+ func test(sep string) {
+ // Successful run
+- cmd := exec.Command("go", "run", "-ldflags=-X main.tbd"+sep+"hello -X main.overwrite"+sep+"trumped -X main.nosuchsymbol"+sep+"neverseen", "linkx.go")
++ cmd := goRun("-ldflags=-X main.tbd"+sep+"hello -X main.overwrite"+sep+"trumped -X main.nosuchsymbol"+sep+"neverseen", "linkx.go")
+ var out, errbuf bytes.Buffer
+ cmd.Stdout = &out
+ cmd.Stderr = &errbuf
+@@ -44,7 +64,7 @@ func test(sep string) {
+ }
+
+ // Issue 8810
+- cmd = exec.Command("go", "run", "-ldflags=-X main.tbd", "linkx.go")
++ cmd = goRun("-ldflags=-X main.tbd", "linkx.go")
+ _, err = cmd.CombinedOutput()
+ if err == nil {
+ fmt.Println("-X linker flag should not accept keys without values")
+@@ -52,7 +72,7 @@ func test(sep string) {
+ }
+
+ // Issue 9621
+- cmd = exec.Command("go", "run", "-ldflags=-X main.b=false -X main.x=42", "linkx.go")
++ cmd = goRun("-ldflags=-X main.b=false -X main.x=42", "linkx.go")
+ outx, err := cmd.CombinedOutput()
+ if err == nil {
+ fmt.Println("-X linker flag should not overwrite non-strings")
+--- test/nosplit.go
++++ test/nosplit.go
+@@ -1,5 +1,5 @@
+ // +build !nacl
+-// run
++// runtarget
+
+ // Copyright 2014 The Go Authors. All rights reserved.
+ // Use of this source code is governed by a BSD-style
+@@ -9,6 +9,7 @@ package main
+
+ import (
+ "bytes"
++ "flag"
+ "fmt"
+ "io/ioutil"
+ "log"
+@@ -16,11 +17,28 @@ import (
+ "os/exec"
+ "path/filepath"
+ "regexp"
+- "runtime"
+ "strconv"
+ "strings"
+ )
+
++var target = flag.String("target", "", "if non empty, use 'go_target' to compile test files and 'go_target_exec' to run the binaries")
++
++func goCmd() string {
++ if *target != "" {
++ return "go_" + *target
++ }
++ return "go"
++}
++
++func goArch() string {
++ goarch, err := exec.Command(goCmd(), "env", "GOARCH").Output()
++ if err != nil {
++ bug()
++ fmt.Printf("running go env GOARCH: %v\n", err)
++ }
++ return strings.TrimSpace(string(goarch))
++}
++
+ var tests = `
+ # These are test cases for the linker analysis that detects chains of
+ # nosplit functions that would cause a stack overflow.
+@@ -193,12 +211,13 @@ var (
+ )
+
+ func main() {
+- goarch := os.Getenv("GOARCH")
++ flag.Parse()
++ goarch := goArch()
+ if goarch == "" {
+- goarch = runtime.GOARCH
++ return
+ }
+
+- version, err := exec.Command("go", "tool", "compile", "-V").Output()
++ version, err := exec.Command(goCmd(), "tool", "compile", "-V").Output()
+ if err != nil {
+ bug()
+ fmt.Printf("running go tool compile -V: %v\n", err)
+@@ -338,7 +357,7 @@ TestCases:
+ log.Fatal(err)
+ }
+
+- cmd := exec.Command("go", "build")
++ cmd := exec.Command(goCmd(), "build")
+ cmd.Dir = dir
+ output, err := cmd.CombinedOutput()
+ if err == nil {
+--- test/run.go
++++ test/run.go
+@@ -220,6 +220,16 @@ func goRun(runcmd runCmd, goname string, args ...string) (out []byte, err error)
+ return runcmd(cmd...)
+ }
+
++func goRunTarget(runcmd runCmd, goname string, args ...string) (out []byte, err error) {
++ cmd := []string{"go_local", "run"}
++ cmd = append(cmd, goname)
++ if *target != "" {
++ cmd = append(cmd, "-target", *target)
++ }
++ cmd = append(cmd, args...)
++ return runcmd(cmd...)
++}
++
+ // skipError describes why a test was skipped.
+ type skipError string
+
+@@ -469,7 +479,7 @@ func (t *test) run() {
+ case "cmpout":
+ action = "run" // the run case already looks for <dir>/<test>.out files
+ fallthrough
+- case "compile", "compiledir", "build", "run", "runoutput", "rundir":
++ case "compile", "compiledir", "build", "run", "runtarget", "runoutput", "rundir":
+ t.action = action
+ case "errorcheck", "errorcheckdir", "errorcheckoutput":
+ t.action = action
+@@ -653,6 +663,17 @@ func (t *test) run() {
+ t.err = fmt.Errorf("incorrect output\n%s", out)
+ }
+
++ case "runtarget":
++ useTmp = false
++ out, err := goRunTarget(runcmd, t.goFileName(), args...)
++ if err != nil {
++ t.err = err
++ return
++ }
++ if strings.Replace(string(out), "\r\n", "\n", -1) != t.expectedOutput() {
++ t.err = fmt.Errorf("incorrect output\n%s", out)
++ }
++
+ case "runoutput":
+ rungatec <- true
+ defer func() {
+--- test/sinit_run.go
++++ test/sinit_run.go
+@@ -1,5 +1,5 @@
+ // +build !nacl
+-// run
++// runtarget
+
+ // Copyright 2014 The Go Authors. All rights reserved.
+ // Use of this source code is governed by a BSD-style
+@@ -11,13 +11,24 @@ package main
+
+ import (
+ "bytes"
++ "flag"
+ "fmt"
+ "os"
+ "os/exec"
+ )
+
++var target = flag.String("target", "", "if non empty, use 'go_target' to compile test files and 'go_target_exec' to run the binaries")
++
++func goCmd() string {
++ if *target != "" {
++ return "go_" + *target
++ }
++ return "go"
++}
++
+ func main() {
+- cmd := exec.Command("go", "tool", "compile", "-S", "sinit.go")
++ flag.Parse()
++ cmd := exec.Command(goCmd(), "tool", "compile", "-S", "sinit.go")
+ out, err := cmd.CombinedOutput()
+ if err != nil {
+ fmt.Println(string(out))
diff --git a/go/patch/go4.patch b/go/patch/go4.patch
new file mode 100644
index 00000000..1c96c093
--- /dev/null
+++ b/go/patch/go4.patch
@@ -0,0 +1,101 @@
+runtime, crypto/x509: add -target flag.
+
+--- src/crypto/x509/x509_test.go
++++ src/crypto/x509/x509_test.go
+@@ -19,6 +19,7 @@ import (
+ "encoding/hex"
+ "encoding/pem"
+ "fmt"
++ "flag"
+ "internal/testenv"
+ "math/big"
+ "net"
+@@ -28,6 +29,8 @@ import (
+ "time"
+ )
+
++var target = flag.String("target", "", "if non empty, use 'go_target' to compile test files and 'go_target_exec' to run the binaries")
++
+ func TestParsePKCS1PrivateKey(t *testing.T) {
+ block, _ := pem.Decode([]byte(pemPrivateKey))
+ priv, err := ParsePKCS1PrivateKey(block.Bytes)
+@@ -862,7 +865,13 @@ func TestParsePEMCRL(t *testing.T) {
+ func TestImports(t *testing.T) {
+ testenv.MustHaveGoRun(t)
+
+- if err := exec.Command("go", "run", "x509_test_import.go").Run(); err != nil {
++ var cmd *exec.Cmd
++ if *target == "" {
++ cmd = exec.Command("go", "run", "x509_test_import.go")
++ } else {
++ cmd = exec.Command("go_"+*target, "run", "-exec", "go_"+*target+"_exec", "x509_test_import.go")
++ }
++ if err := cmd.Run(); err != nil {
+ t.Errorf("failed to run x509_test_import.go: %s", err)
+ }
+ }
+--- src/runtime/crash_test.go
++++ src/runtime/crash_test.go
+@@ -5,6 +5,7 @@
+ package runtime_test
+
+ import (
++ "flag"
+ "fmt"
+ "internal/testenv"
+ "io/ioutil"
+@@ -18,6 +19,25 @@ import (
+ "testing"
+ )
+
++var target = flag.String("target", "", "if non empty, use 'go_target' to compile test files and 'go_target_exec' to run the binaries")
++
++func goCmd() string {
++ if *target != "" {
++ return "go_" + *target
++ }
++ return "go"
++}
++
++func goExecCmd(name string, arg ...string) *exec.Cmd {
++ var cmd []string
++ if *target != "" {
++ cmd = append(cmd, "go_"+*target+"_exec")
++ }
++ cmd = append(cmd, name)
++ cmd = append(cmd, arg...)
++ return exec.Command(cmd[0], cmd[1:]...)
++}
++
+ var toRemove []string
+
+ func TestMain(m *testing.M) {
+@@ -65,7 +85,7 @@ func runTestProg(t *testing.T, binary, name string) string {
+ if err != nil {
+ t.Fatal(err)
+ }
+- got, _ := testEnv(exec.Command(exe, name)).CombinedOutput()
++ got, _ := testEnv(goExecCmd(exe, name)).CombinedOutput()
+ return string(got)
+ }
+
+@@ -92,7 +112,7 @@ func buildTestProg(t *testing.T, binary string) (string, error) {
+ }
+
+ exe := filepath.Join(testprog.dir, binary+".exe")
+- cmd := exec.Command("go", "build", "-o", exe)
++ cmd := exec.Command(goCmd(), "build", "-o", exe)
+ cmd.Dir = "testdata/" + binary
+ out, err := testEnv(cmd).CombinedOutput()
+ if err != nil {
+--- src/runtime/crash_unix_test.go
++++ src/runtime/crash_unix_test.go
+@@ -157,7 +157,7 @@ func TestSignalExitStatus(t *testing.T) {
+ if err != nil {
+ t.Fatal(err)
+ }
+- err = testEnv(exec.Command(exe, "SignalExitStatus")).Run()
++ err = testEnv(goExecCmd(exe, "SignalExitStatus")).Run()
+ if err == nil {
+ t.Error("test program succeeded unexpectedly")
+ } else if ee, ok := err.(*exec.ExitError); !ok {
diff --git a/go/patch/go5.patch b/go/patch/go5.patch
new file mode 100644
index 00000000..fa656586
--- /dev/null
+++ b/go/patch/go5.patch
@@ -0,0 +1,198 @@
+misc/cgo/testcshared: add support for -target.
+
+--- misc/cgo/testcshared/test.bash
++++ misc/cgo/testcshared/test.bash
+@@ -14,9 +14,23 @@ if [ ! -f src/libgo/libgo.go ]; then
+ exit 1
+ fi
+
+-goos=$(go env GOOS)
+-goarch=$(go env GOARCH)
+-goroot=$(go env GOROOT)
++function target()
++ {
++ [[ -n "${target}" ]]
++ }
++
++function go_target()
++ {
++ if target; then
++ go_${target} "$@"
++ else
++ go "$@"
++ fi
++ }
++
++goos=$(go_target env GOOS)
++goarch=$(go_target env GOARCH)
++goroot=$(go_target env GOROOT)
+ if [ ! -d "$goroot" ]; then
+ echo 'misc/cgo/testcshared/test.bash cannnot find GOROOT' 1>&2
+ echo '$GOROOT:' "$GOROOT" 1>&2
+@@ -31,8 +45,10 @@ if [ "${goos}" == "darwin" ]; then
+ installdir=pkg/${goos}_${goarch}_testcshared
+ fi
+
+-# Temporary directory on the android device.
+-androidpath=/data/local/tmp/testcshared-$$
++# Temporary directory on the android/chromeos device.
++if target; then
++ remotepath=$(target_tmpdir)/testcshared-$$
++fi
+
+ function cleanup() {
+ rm -f libgo.$libext libgo2.$libext libgo4.$libext libgo5.$libext
+@@ -40,37 +56,33 @@ function cleanup() {
+ rm -f testp testp2 testp3 testp4 testp5
+ rm -rf pkg "${goroot}/${installdir}"
+
+- if [ "$goos" == "android" ]; then
+- adb shell rm -rf "$androidpath"
++ if target; then
++ target_sh "${target}" "rm -rf $remotepath"
+ fi
+ }
+ trap cleanup EXIT
+
+-if [ "$goos" == "android" ]; then
+- adb shell mkdir -p "$androidpath"
++if target; then
++ target_sh "${target}" "mkdir -p $remotepath"
+ fi
+
+ function run() {
+- case "$goos" in
+- "android")
++ if target; then
+ local args=$@
+- output=$(adb shell "cd ${androidpath}; $@")
+- output=$(echo $output|tr -d '\r')
++ output=$(target_sh "${target}" "cd ${remotepath}; $@")
+ case $output in
+ *PASS) echo "PASS";;
+ *) echo "$output";;
+ esac
+- ;;
+- *)
++ else
+ echo $(env $@)
+- ;;
+- esac
++ fi
+ }
+
+ function binpush() {
+ bin=${1}
+- if [ "$goos" == "android" ]; then
+- adb push "$bin" "${androidpath}/${bin}" 2>/dev/null
++ if target; then
++ target_cp "$bin" "${target}:${remotepath}/${bin}"
+ fi
+ }
+
+@@ -84,9 +96,9 @@ if [ "$goos" == "darwin" ]; then
+ fi
+
+ # Create the header files.
+-GOPATH=$(pwd) go install -buildmode=c-shared $suffix libgo
++GOPATH=$(pwd) go_target install -buildmode=c-shared $suffix libgo
+
+-GOPATH=$(pwd) go build -buildmode=c-shared $suffix -o libgo.$libext src/libgo/libgo.go
++GOPATH=$(pwd) go_target build -buildmode=c-shared $suffix -o libgo.$libext src/libgo/libgo.go
+ binpush libgo.$libext
+
+ if [ "$goos" == "linux" ] || [ "$goos" == "android" ] ; then
+@@ -96,8 +108,8 @@ if [ "$goos" == "linux" ] || [ "$goos" == "android" ] ; then
+ fi
+ fi
+
+-GOGCCFLAGS=$(go env GOGCCFLAGS)
+-if [ "$goos" == "android" ]; then
++GOGCCFLAGS=$(go_target env GOGCCFLAGS)
++if target; then
+ GOGCCFLAGS="${GOGCCFLAGS} -pie"
+ fi
+
+@@ -105,7 +117,7 @@ status=0
+
+ # test0: exported symbols in shared lib are accessible.
+ # TODO(iant): using _shared here shouldn't really be necessary.
+-$(go env CC) ${GOGCCFLAGS} -I ${installdir} -o testp main0.c libgo.$libext
++$(go_target env CC) ${GOGCCFLAGS} -I ${installdir} -o testp main0.c libgo.$libext
+ binpush testp
+
+ output=$(run LD_LIBRARY_PATH=. ./testp)
+@@ -115,7 +127,7 @@ if [ "$output" != "PASS" ]; then
+ fi
+
+ # test1: shared library can be dynamically loaded and exported symbols are accessible.
+-$(go env CC) ${GOGCCFLAGS} -o testp main1.c -ldl
++$(go_target env CC) ${GOGCCFLAGS} -o testp main1.c -ldl
+ binpush testp
+ output=$(run ./testp ./libgo.$libext)
+ if [ "$output" != "PASS" ]; then
+@@ -124,13 +136,13 @@ if [ "$output" != "PASS" ]; then
+ fi
+
+ # test2: tests libgo2 which does not export any functions.
+-GOPATH=$(pwd) go build -buildmode=c-shared $suffix -o libgo2.$libext libgo2
++GOPATH=$(pwd) go_target build -buildmode=c-shared $suffix -o libgo2.$libext libgo2
+ binpush libgo2.$libext
+ linkflags="-Wl,--no-as-needed"
+ if [ "$goos" == "darwin" ]; then
+ linkflags=""
+ fi
+-$(go env CC) ${GOGCCFLAGS} -o testp2 main2.c $linkflags libgo2.$libext
++$(go_target env CC) ${GOGCCFLAGS} -o testp2 main2.c $linkflags libgo2.$libext
+ binpush testp2
+ output=$(run LD_LIBRARY_PATH=. ./testp2)
+ if [ "$output" != "PASS" ]; then
+@@ -138,9 +150,9 @@ if [ "$output" != "PASS" ]; then
+ status=1
+ fi
+
+-# test3: tests main.main is exported on android.
+-if [ "$goos" == "android" ]; then
+- $(go env CC) ${GOGCCFLAGS} -o testp3 main3.c -ldl
++# test3: tests main.main is exported on android/chromeos.
++if target; then
++ $(go_target env CC) ${GOGCCFLAGS} -o testp3 main3.c -ldl
+ binpush testp3
+ output=$(run ./testp ./libgo.so)
+ if [ "$output" != "PASS" ]; then
+@@ -150,14 +162,14 @@ if [ "$goos" == "android" ]; then
+ fi
+
+ # test4: tests signal handlers
+-GOPATH=$(pwd) go build -buildmode=c-shared $suffix -o libgo4.$libext libgo4
++GOPATH=$(pwd) go_target build -buildmode=c-shared $suffix -o libgo4.$libext libgo4
+ binpush libgo4.$libext
+-$(go env CC) ${GOGCCFLAGS} -pthread -o testp4 main4.c -ldl
++$(go_target env CC) ${GOGCCFLAGS} -pthread -o testp4 main4.c -ldl
+ binpush testp4
+ output=$(run ./testp4 ./libgo4.$libext 2>&1)
+ if test "$output" != "PASS"; then
+ echo "FAIL test4 got ${output}"
+- if test "$goos" != "android"; then
++ if ! target; then
+ echo "re-running test4 in verbose mode"
+ ./testp4 ./libgo4.$libext verbose
+ fi
+@@ -165,14 +177,14 @@ if test "$output" != "PASS"; then
+ fi
+
+ # test5: tests signal handlers with os/signal.Notify
+-GOPATH=$(pwd) go build -buildmode=c-shared $suffix -o libgo5.$libext libgo5
++GOPATH=$(pwd) go_target build -buildmode=c-shared $suffix -o libgo5.$libext libgo5
+ binpush libgo5.$libext
+-$(go env CC) ${GOGCCFLAGS} -pthread -o testp5 main5.c -ldl
++$(go_target env CC) ${GOGCCFLAGS} -pthread -o testp5 main5.c -ldl
+ binpush testp5
+ output=$(run ./testp5 ./libgo5.$libext 2>&1)
+ if test "$output" != "PASS"; then
+ echo "FAIL test5 got ${output}"
+- if test "$goos" != "android"; then
++ if ! target; then
+ echo "re-running test5 in verbose mode"
+ ./testp5 ./libgo5.$libext verbose
+ fi
diff --git a/go/patch/go6.patch b/go/patch/go6.patch
new file mode 100644
index 00000000..7f1e4c0e
--- /dev/null
+++ b/go/patch/go6.patch
@@ -0,0 +1,65 @@
+runtime: deadlock detection does not work when using external linker.
+
+--- src/runtime/crash_test.go
++++ src/runtime/crash_test.go
+@@ -177,22 +177,27 @@ func testDeadlock(t *testing.T, name string) {
+ }
+
+ func TestSimpleDeadlock(t *testing.T) {
++ t.Skip("deadlock detection fails with external linker")
+ testDeadlock(t, "SimpleDeadlock")
+ }
+
+ func TestInitDeadlock(t *testing.T) {
++ t.Skip("deadlock detection fails with external linker")
+ testDeadlock(t, "InitDeadlock")
+ }
+
+ func TestLockedDeadlock(t *testing.T) {
++ t.Skip("deadlock detection fails with external linker")
+ testDeadlock(t, "LockedDeadlock")
+ }
+
+ func TestLockedDeadlock2(t *testing.T) {
++ t.Skip("deadlock detection fails with external linker")
+ testDeadlock(t, "LockedDeadlock2")
+ }
+
+ func TestGoexitDeadlock(t *testing.T) {
++ t.Skip("deadlock detection fails with external linker")
+ output := runTestProg(t, "testprog", "GoexitDeadlock")
+ want := "no goroutines (main called runtime.Goexit) - deadlock!"
+ if !strings.Contains(output, want) {
+@@ -229,6 +234,7 @@ panic: again
+ }
+
+ func TestGoexitCrash(t *testing.T) {
++ t.Skip("deadlock detection fails with external linker")
+ output := runTestProg(t, "testprog", "GoexitExit")
+ want := "no goroutines (main called runtime.Goexit) - deadlock!"
+ if !strings.Contains(output, want) {
+@@ -285,6 +291,7 @@ func TestBreakpoint(t *testing.T) {
+ }
+
+ func TestGoexitInPanic(t *testing.T) {
++ t.Skip("deadlock detection fails with external linker")
+ // see issue 8774: this code used to trigger an infinite recursion
+ output := runTestProg(t, "testprog", "GoexitInPanic")
+ want := "fatal error: no goroutines (main called runtime.Goexit) - deadlock!"
+@@ -303,6 +310,7 @@ func TestPanicAfterGoexit(t *testing.T) {
+ }
+
+ func TestRecoveredPanicAfterGoexit(t *testing.T) {
++ t.Skip("deadlock detection fails with external linker")
+ output := runTestProg(t, "testprog", "RecoveredPanicAfterGoexit")
+ want := "fatal error: no goroutines (main called runtime.Goexit) - deadlock!"
+ if !strings.HasPrefix(output, want) {
+--- test/fixedbugs/bug429_run.go
++++ test/fixedbugs/bug429_run.go
+@@ -1,5 +1,5 @@
+ // +build !nacl
+-// runtarget
++// skip
+
+ // Copyright 2014 The Go Authors. All rights reserved.
+ // Use of this source code is governed by a BSD-style
diff --git a/go/patch/go7.patch b/go/patch/go7.patch
new file mode 100644
index 00000000..7b769cf4
--- /dev/null
+++ b/go/patch/go7.patch
@@ -0,0 +1,139 @@
+all: disable some tests that take a long time or allocate a lot of memory.
+
+--- src/encoding/gob/encoder_test.go
++++ src/encoding/gob/encoder_test.go
+@@ -1003,10 +1003,7 @@ func TestBadData(t *testing.T) {
+
+ // TestHugeWriteFails tests that enormous messages trigger an error.
+ func TestHugeWriteFails(t *testing.T) {
+- if testing.Short() {
+- // Requires allocating a monster, so don't do this from all.bash.
+- t.Skip("skipping huge allocation in short mode")
+- }
++ t.Skip("skipping test due to huge memory requirement")
+ huge := make([]byte, tooBig)
+ huge[0] = 7 // Make sure it's not all zeros.
+ buf := new(bytes.Buffer)
+--- src/math/big/float_test.go
++++ src/math/big/float_test.go
+@@ -1428,10 +1428,7 @@ func TestFloatQuo(t *testing.T) {
+ // TestFloatQuoSmoke tests all divisions x/y for values x, y in the range [-n, +n];
+ // it serves as a smoke test for basic correctness of division.
+ func TestFloatQuoSmoke(t *testing.T) {
+- n := 1000
+- if testing.Short() {
+- n = 10
+- }
++ n := 10
+
+ const dprec = 3 // max. precision variation
+ const prec = 10 + dprec // enough bits to hold n precisely
+--- src/math/big/rat_test.go
++++ src/math/big/rat_test.go
+@@ -430,10 +430,7 @@ func TestFloat64Distribution(t *testing.T) {
+ 9,
+ 11,
+ }
+- var winc, einc = uint64(1), 1 // soak test (~75s on x86-64)
+- if testing.Short() {
+- winc, einc = 10, 500 // quick test (~12ms on x86-64)
+- }
++ var winc, einc = uint64(10), 500
+
+ for _, sign := range "+-" {
+ for _, a := range add {
+--- src/math/big/ratconv_test.go
++++ src/math/big/ratconv_test.go
+@@ -344,9 +344,7 @@ func isFinite(f float64) bool {
+ func TestFloat32SpecialCases(t *testing.T) {
+ for _, input := range float64inputs {
+ if strings.HasPrefix(input, "long:") {
+- if testing.Short() {
+- continue
+- }
++ continue
+ input = input[len("long:"):]
+ }
+
+@@ -400,9 +398,7 @@ func TestFloat32SpecialCases(t *testing.T) {
+ func TestFloat64SpecialCases(t *testing.T) {
+ for _, input := range float64inputs {
+ if strings.HasPrefix(input, "long:") {
+- if testing.Short() {
+- continue
+- }
++ continue
+ input = input[len("long:"):]
+ }
+
+--- src/net/dial_test.go
++++ src/net/dial_test.go
+@@ -77,10 +77,7 @@ func TestSelfConnect(t *testing.T) {
+ l.Close()
+
+ // Try to connect to that address repeatedly.
+- n := 100000
+- if testing.Short() {
+- n = 1000
+- }
++ n := 1000
+ switch runtime.GOOS {
+ case "darwin", "dragonfly", "freebsd", "netbsd", "openbsd", "plan9", "solaris", "windows":
+ // Non-Linux systems take a long time to figure
+--- src/runtime/fastlog2_test.go
++++ src/runtime/fastlog2_test.go
+@@ -16,11 +16,7 @@ func TestFastLog2(t *testing.T) {
+ const randomBitCount = 26
+ var e float64
+
+- inc := 1
+- if testing.Short() {
+- // Check 1K total values, down from 64M.
+- inc = 1 << 16
+- }
++ inc := 1 << 16
+ for i := 1; i < 1<<randomBitCount; i += inc {
+ l, fl := math.Log2(float64(i)), runtime.Fastlog2(float64(i))
+ d := l - fl
+--- src/runtime/hash_test.go
++++ src/runtime/hash_test.go
+@@ -126,9 +126,7 @@ func TestSmhasherZeros(t *testing.T) {
+
+ // Strings with up to two nonzero bytes all have distinct hashes.
+ func TestSmhasherTwoNonzero(t *testing.T) {
+- if testing.Short() {
+- t.Skip("Skipping in short mode")
+- }
++ t.Skip("skipping test due to huge memory requirement")
+ h := newHashSet()
+ for n := 2; n <= 16; n++ {
+ twoNonZero(h, n)
+@@ -229,9 +227,7 @@ func setbits(h *HashSet, b []byte, i int, k int) {
+ // Test all possible combinations of n blocks from the set s.
+ // "permutation" is a bad name here, but it is what Smhasher uses.
+ func TestSmhasherPermutation(t *testing.T) {
+- if testing.Short() {
+- t.Skip("Skipping in short mode")
+- }
++ t.Skip("skipping test due to huge memory requirement")
+ permutation(t, []uint32{0, 1, 2, 3, 4, 5, 6, 7}, 8)
+ permutation(t, []uint32{0, 1 << 29, 2 << 29, 3 << 29, 4 << 29, 5 << 29, 6 << 29, 7 << 29}, 8)
+ permutation(t, []uint32{0, 1}, 20)
+--- src/runtime/pprof/pprof_test.go
++++ src/runtime/pprof/pprof_test.go
+@@ -257,14 +257,7 @@ func profileOk(t *testing.T, need []string, prof bytes.Buffer, duration time.Dur
+ func TestCPUProfileWithFork(t *testing.T) {
+ testenv.MustHaveExec(t)
+
+- heap := 1 << 30
+- if runtime.GOOS == "android" {
+- // Use smaller size for Android to avoid crash.
+- heap = 100 << 20
+- }
+- if testing.Short() {
+- heap = 100 << 20
+- }
++ heap := 100 << 20
+ // This makes fork slower.
+ garbage := make([]byte, heap)
+ // Need to touch the slice, otherwise it won't be paged in.
diff --git a/go/push_goroot b/go/push_goroot
new file mode 100755
index 00000000..41612f72
--- /dev/null
+++ b/go/push_goroot
@@ -0,0 +1,34 @@
+#!/bin/bash
+set -e -o pipefail
+
+# This script copies a locally built GOROOT to a remote device.
+#
+# Usage: push_goroot <target>...
+#
+# This script can work with both ChromeOS/Android devices.
+#
+# It uses "target_tmpdir" to figure out where to copy GOROOT on the device.
+# It uses "target_sh" to remotely execute commands on the device.
+# It uses "target_cp" to transfer files to the device.
+
+goroot="$(target_tmpdir)/go"
+for target in "$@"
+do
+ echo -n "pushing to ${target} ... "
+ target_sh ${target} "rm -rf ${goroot}"
+ target_sh ${target} "mkdir -p ${goroot}/pkg"
+
+ pkgdir="$(go_${target} env GOOS)_$(go_${target} env GOARCH)"
+ if [[ -d "pkg/${pkgdir}_shared" ]]
+ then
+ target_cp "pkg/${pkgdir}_shared" ${target}:${goroot}/pkg
+ target_sh ${target} "ln -s ${pkgdir}_shared ${goroot}/pkg/${pkgdir}"
+ else
+ target_cp "pkg/${pkgdir}" ${target}:${goroot}/pkg
+ fi
+
+ target_cp "src" ${target}:${goroot}
+ target_cp "lib" ${target}:${goroot}
+ target_cp "test" ${target}:${goroot}
+ echo "done"
+done
diff --git a/go/test_go b/go/test_go
new file mode 100755
index 00000000..3740c1b7
--- /dev/null
+++ b/go/test_go
@@ -0,0 +1,88 @@
+#!/bin/bash
+
+# This script runs tests for the Go toolchain on target devices.
+# It can be used for both ChromeOS and Android targets.
+#
+# Many of the test drivers that come from upstream do not support
+# cross-compiling and running the tests remotely. The patches in
+# the ./patch/ directory must be applied to the upstream sources
+# to add this support.
+#
+# Usage: test_go [-v] [-vv] [-full] <target>...
+# -v: enable verbose test output from compiler tests.
+# -v: enable verbose test output from standard library tests.
+# -full: run all standard library tests (without the -short flag).
+
+verbose_run_test=""
+verbose_go_test=""
+testflags="-short"
+while [[ "$1" == -* ]]
+do
+ case "$1" in
+ -v) verbose_run_test="-v" ;;
+ -vv) verbose_go_test="-v" ;;
+ -full) testflags="-timeout=2h" ;;
+ *) echo "unrecognized flag: $1" ;;
+ esac
+ shift
+done
+
+go_local build -o runtest test/run.go
+runtest="${PWD}/runtest"
+
+function run_test()
+ {
+ GOOS="$(go_${target} env GOOS)" GOARCH="$(go_${target} env GOARCH)" ${runtest} -n=1 ${verbose_run_test} -show_skips -summary -target="${target}" "$@"
+ }
+
+function go_test()
+ {
+ go_${target} test -p=1 ${verbose_go_test} -exec="go_${target}_exec" ${testflags} "$@"
+ }
+
+function go_test_target()
+ {
+ go_local test -p=1 ${verbose_go_test} ${testflags} "$@" -target="${target}"
+ }
+
+for target in "$@"
+do
+ echo
+ echo "## ${target}"
+
+ echo
+ echo "# test"
+ (cd test && run_test)
+
+ echo
+ echo "# std"
+ go_test std
+
+ echo
+ echo "# GOMAXPROCS=2 -cpu=1,2,4 runtime"
+ GOMAXPROCS=2 go_test -cpu=1,2,4 runtime
+
+ echo
+ echo "# -cpu=10 sync"
+ go_test -cpu=10 sync
+
+ echo
+ echo "# runtime crypto/x509 -target=${target}"
+ go_test_target runtime crypto/x509
+
+ echo
+ echo "# misc/cgo/{stdio,life}"
+ run_test misc/cgo/{stdio,life}
+
+ echo
+ echo "# misc/cgo/{test,testtls,nocgo}"
+ GOTRACEBACK=2 go_test ./misc/cgo/{test,testtls,nocgo}
+
+ echo
+ echo "# misc/cgo/testcshared"
+ (cd misc/cgo/testcshared && target="${target}" ./test.bash)
+
+ echo
+ echo "# misc/cgo/testsigfwd"
+ (cd misc/cgo/testsigfwd && go_${target} run -exec="go_${target}_exec" main.go)
+done