cmd/gomobile: expose goVersion to subcommands

Pulled out of golang.org/cl/16913.

Change-Id: I041aba4e8cefed95ee2935139571140164b5d677
Reviewed-on: https://go-review.googlesource.com/17001
Reviewed-by: Hyang-Ah Hana Kim <hyangah@gmail.com>
diff --git a/cmd/gomobile/env.go b/cmd/gomobile/env.go
index 21de3a8..f67b3a2 100644
--- a/cmd/gomobile/env.go
+++ b/cmd/gomobile/env.go
@@ -48,14 +48,9 @@
 
 	// Check the toolchain is in a good state.
 	// Pick a temporary directory for assembling an apk/app.
-	version, err := goVersion()
-	if err != nil {
-		return nil, err
-	}
 	if gomobilepath == "" {
 		return nil, errors.New("toolchain not installed, run `gomobile init`")
 	}
-
 	cleanupFn := func() {
 		if buildWork {
 			fmt.Printf("WORK=%s\n", tmpdir)
@@ -72,7 +67,7 @@
 		if err != nil {
 			return nil, errors.New("toolchain partially installed, run `gomobile init`")
 		}
-		if !bytes.Equal(installedVersion, version) {
+		if !bytes.Equal(installedVersion, goVersionOut) {
 			return nil, errors.New("toolchain out of date, run `gomobile init`")
 		}
 
diff --git a/cmd/gomobile/init.go b/cmd/gomobile/init.go
index e0c0f9a..0dc6dfb 100644
--- a/cmd/gomobile/init.go
+++ b/cmd/gomobile/init.go
@@ -38,7 +38,6 @@
 var (
 	goos    = runtime.GOOS
 	goarch  = runtime.GOARCH
-	goTool  = go1_6
 	ndkarch string
 )
 
@@ -77,14 +76,6 @@
 }
 
 func runInit(cmd *command) error {
-	version, err := goVersion()
-	if err != nil {
-		return fmt.Errorf("%v: %s", err, version)
-	}
-	if bytes.HasPrefix(version, []byte("go version go1.5")) {
-		goTool = go1_5
-	}
-
 	gopaths := filepath.SplitList(goEnv("GOPATH"))
 	if len(gopaths) == 0 {
 		return fmt.Errorf("GOPATH is not set")
@@ -150,7 +141,7 @@
 	// Install standard libraries for cross compilers.
 	start := time.Now()
 	var androidArgs []string
-	if goTool == go1_6 {
+	if goVersion == go1_6 {
 		// Ideally this would be -buildmode=c-shared.
 		// https://golang.org/issue/13234.
 		androidArgs = []string{"-gcflags=-shared", "-ldflags=-shared"}
@@ -166,7 +157,7 @@
 		printcmd("go version > %s", verpath)
 	}
 	if !buildN {
-		if err := ioutil.WriteFile(verpath, version, 0644); err != nil {
+		if err := ioutil.WriteFile(verpath, goVersionOut, 0644); err != nil {
 			return err
 		}
 	}
@@ -306,14 +297,6 @@
 	return os.Remove(name)
 }
 
-func goVersion() ([]byte, error) {
-	gobin, err := exec.LookPath("go")
-	if err != nil {
-		return nil, fmt.Errorf("go not found")
-	}
-	return exec.Command(gobin, "version").CombinedOutput()
-}
-
 func fetchOpenAL() error {
 	url := "https://dl.google.com/go/mobile/gomobile-" + openALVersion + ".tar.gz"
 	archive, err := fetch(url)
@@ -676,10 +659,3 @@
 	}
 	return nil
 }
-
-type goToolVersion int
-
-const (
-	go1_5 goToolVersion = iota
-	go1_6
-)
diff --git a/cmd/gomobile/init_test.go b/cmd/gomobile/init_test.go
index 9445847..8d73a28 100644
--- a/cmd/gomobile/init_test.go
+++ b/cmd/gomobile/init_test.go
@@ -132,7 +132,7 @@
 go install -p={{.NumCPU}} -x golang.org/x/mobile/gl
 go install -p={{.NumCPU}} -x golang.org/x/mobile/app
 go install -p={{.NumCPU}} -x golang.org/x/mobile/exp/app/debug{{end}}
-GOOS=android GOARCH=arm GOARM=7 CC=$GOMOBILE/android-{{.NDK}}/arm/bin/arm-linux-androideabi-gcc{{.EXE}} CXX=$GOMOBILE/android-{{.NDK}}/arm/bin/arm-linux-androideabi-g++{{.EXE}} CGO_ENABLED=1 go install -p={{.NumCPU}} -buildmode=c-shared -pkgdir=$GOMOBILE/pkg_android_arm -x std
+GOOS=android GOARCH=arm GOARM=7 CC=$GOMOBILE/android-{{.NDK}}/arm/bin/arm-linux-androideabi-gcc{{.EXE}} CXX=$GOMOBILE/android-{{.NDK}}/arm/bin/arm-linux-androideabi-g++{{.EXE}} CGO_ENABLED=1 go install -p={{.NumCPU}} -pkgdir=$GOMOBILE/pkg_android_arm -x std
 {{if eq .GOOS "darwin"}}GOOS=darwin GOARCH=arm GOARM=7 CC=clang-iphoneos CXX=clang-iphoneos CGO_CFLAGS=-isysroot=iphoneos -arch armv7 CGO_LDFLAGS=-isysroot=iphoneos -arch armv7 CGO_ENABLED=1 go install -p={{.NumCPU}} -pkgdir=$GOMOBILE/pkg_darwin_arm -x std
 GOOS=darwin GOARCH=arm64 CC=clang-iphoneos CXX=clang-iphoneos CGO_CFLAGS=-isysroot=iphoneos -arch arm64 CGO_LDFLAGS=-isysroot=iphoneos -arch arm64 CGO_ENABLED=1 go install -p={{.NumCPU}} -pkgdir=$GOMOBILE/pkg_darwin_arm64 -x std
 GOOS=darwin GOARCH=amd64 CC=clang-iphonesimulator CXX=clang-iphonesimulator CGO_CFLAGS=-isysroot=iphonesimulator -mios-simulator-version-min=6.1 -arch x86_64 CGO_LDFLAGS=-isysroot=iphonesimulator -mios-simulator-version-min=6.1 -arch x86_64 CGO_ENABLED=1 go install -p={{.NumCPU}} -tags=ios -pkgdir=$GOMOBILE/pkg_darwin_amd64 -x std
diff --git a/cmd/gomobile/main.go b/cmd/gomobile/main.go
index 60b8d55..b17d93d 100644
--- a/cmd/gomobile/main.go
+++ b/cmd/gomobile/main.go
@@ -9,6 +9,7 @@
 import (
 	"bufio"
 	"bytes"
+	"errors"
 	"flag"
 	"fmt"
 	"html/template"
@@ -16,10 +17,17 @@
 	"io/ioutil"
 	"log"
 	"os"
+	"os/exec"
 	"unicode"
 	"unicode/utf8"
 )
 
+var (
+	gomobileName = "gomobile"
+	goVersionOut = []byte(nil)
+	goVersion    = go1_5
+)
+
 func printUsage(w io.Writer) {
 	bufw := bufio.NewWriter(w)
 	if err := usageTmpl.Execute(bufw, commands); err != nil {
@@ -28,8 +36,6 @@
 	bufw.Flush()
 }
 
-var gomobileName = "gomobile"
-
 func main() {
 	gomobileName = os.Args[0]
 	flag.Usage = func() {
@@ -53,6 +59,11 @@
 		return
 	}
 
+	if err := determineGoVersion(); err != nil {
+		fmt.Fprintf(os.Stderr, "%s: %v\n", gomobileName, err)
+		os.Exit(1)
+	}
+
 	for _, cmd := range commands {
 		if cmd.Name == args[0] {
 			cmd.flag.Usage = func() {
@@ -74,6 +85,33 @@
 	os.Exit(2)
 }
 
+type goToolVersion int
+
+const (
+	go1_5 goToolVersion = iota
+	go1_6
+)
+
+func determineGoVersion() error {
+	gobin, err := exec.LookPath("go")
+	if err != nil {
+		return errors.New("go not found")
+	}
+	goVersionOut, err = exec.Command(gobin, "version").CombinedOutput()
+	if err != nil {
+		return fmt.Errorf("'go version' failed: %v, %s", err, goVersionOut)
+	}
+	switch {
+	case bytes.HasPrefix(goVersionOut, []byte("go version go1.4")):
+		return errors.New("Go 1.5 or newer is required")
+	case bytes.HasPrefix(goVersionOut, []byte("go version go1.5")):
+		goVersion = go1_5
+	default:
+		goVersion = go1_6 // assume developers are working at tip
+	}
+	return nil
+}
+
 func help(args []string) {
 	if len(args) == 0 {
 		printUsage(os.Stdout)