cmd/gomobile: make sure gobind is installed and updated

When running gomobile bind, make sure gobind exists. If not, instruct
the user to run gomobile init which will go install gobind.

Change-Id: I2d064ba58874fd5581c17417124561f3d1fb6b83
Reviewed-on: https://go-review.googlesource.com/101055
Reviewed-by: Hyang-Ah Hana Kim <hyangah@gmail.com>
diff --git a/cmd/gomobile/bind.go b/cmd/gomobile/bind.go
index 410fc4e..3105db6 100644
--- a/cmd/gomobile/bind.go
+++ b/cmd/gomobile/bind.go
@@ -11,6 +11,7 @@
 	"io"
 	"io/ioutil"
 	"os"
+	"os/exec"
 	"path"
 	"path/filepath"
 )
@@ -96,6 +97,16 @@
 		return errors.New("no Android NDK path is set. Please run gomobile init with the ndk-bundle installed through the Android SDK manager or with the -ndk flag set.")
 	}
 
+	var gobind string
+	if !buildN {
+		gobind, err = exec.LookPath("gobind")
+		if err != nil {
+			return errors.New("gobind was not found. Please run gomobile init before trying again.")
+		}
+	} else {
+		gobind = "gobind"
+	}
+
 	var pkgs []*build.Package
 	switch len(args) {
 	case 0:
@@ -117,10 +128,10 @@
 
 	switch targetOS {
 	case "android":
-		return goAndroidBind(pkgs, targetArchs)
+		return goAndroidBind(gobind, pkgs, targetArchs)
 	case "darwin":
 		// TODO: use targetArchs?
-		return goIOSBind(pkgs)
+		return goIOSBind(gobind, pkgs)
 	default:
 		return fmt.Errorf(`invalid -target=%q`, buildTarget)
 	}
diff --git a/cmd/gomobile/bind_androidapp.go b/cmd/gomobile/bind_androidapp.go
index ee24c95..45a8c37 100644
--- a/cmd/gomobile/bind_androidapp.go
+++ b/cmd/gomobile/bind_androidapp.go
@@ -17,14 +17,14 @@
 	"strings"
 )
 
-func goAndroidBind(pkgs []*build.Package, androidArchs []string) error {
+func goAndroidBind(gobind string, pkgs []*build.Package, androidArchs []string) error {
 	if sdkDir := os.Getenv("ANDROID_HOME"); sdkDir == "" {
 		return fmt.Errorf("this command requires ANDROID_HOME environment variable (path to the Android SDK)")
 	}
 
 	// Run gobind to generate the bindings
 	cmd := exec.Command(
-		"gobind",
+		gobind,
 		"-lang=go,java",
 		"-outdir="+tmpdir,
 	)
diff --git a/cmd/gomobile/bind_iosapp.go b/cmd/gomobile/bind_iosapp.go
index c2b9499..1c9d698 100644
--- a/cmd/gomobile/bind_iosapp.go
+++ b/cmd/gomobile/bind_iosapp.go
@@ -16,10 +16,10 @@
 	"text/template"
 )
 
-func goIOSBind(pkgs []*build.Package) error {
+func goIOSBind(gobind string, pkgs []*build.Package) error {
 	// Run gobind to generate the bindings
 	cmd := exec.Command(
-		"gobind",
+		gobind,
 		"-lang=go,objc",
 		"-outdir="+tmpdir,
 	)
diff --git a/cmd/gomobile/build_darwin_test.go b/cmd/gomobile/build_darwin_test.go
index 3bc8ef4..50dc864 100644
--- a/cmd/gomobile/build_darwin_test.go
+++ b/cmd/gomobile/build_darwin_test.go
@@ -26,7 +26,11 @@
 	buildTarget = "ios"
 	gopath = filepath.SplitList(os.Getenv("GOPATH"))[0]
 	cmdBuild.flag.Parse([]string{"golang.org/x/mobile/example/basic"})
+	oldTags := ctx.BuildTags
 	ctx.BuildTags = []string{"tag1"}
+	defer func() {
+		ctx.BuildTags = oldTags
+	}()
 	err := runBuild(cmdBuild)
 	if err != nil {
 		t.Log(buf.String())
diff --git a/cmd/gomobile/build_test.go b/cmd/gomobile/build_test.go
index 9bd8ff4..97af848 100644
--- a/cmd/gomobile/build_test.go
+++ b/cmd/gomobile/build_test.go
@@ -81,7 +81,11 @@
 		os.Setenv("HOMEDRIVE", "C:")
 	}
 	cmdBuild.flag.Parse([]string{"golang.org/x/mobile/example/basic"})
+	oldTags := ctx.BuildTags
 	ctx.BuildTags = []string{"tag1"}
+	defer func() {
+		ctx.BuildTags = oldTags
+	}()
 	err := runBuild(cmdBuild)
 	if err != nil {
 		t.Log(buf.String())
diff --git a/cmd/gomobile/init.go b/cmd/gomobile/init.go
index ba040cd..79d6d88 100644
--- a/cmd/gomobile/init.go
+++ b/cmd/gomobile/init.go
@@ -85,6 +85,11 @@
 		removeAll(tmpdir)
 	}()
 
+	// Make sure gobind is up to date.
+	if err := goInstall([]string{"golang.org/x/mobile/cmd/gobind"}, nil); err != nil {
+		return err
+	}
+
 	if buildN {
 		initNDK = "$NDK_PATH"
 		initOpenAL = "$OPENAL_PATH"
diff --git a/cmd/gomobile/init_test.go b/cmd/gomobile/init_test.go
index d8488e1..b883b76 100644
--- a/cmd/gomobile/init_test.go
+++ b/cmd/gomobile/init_test.go
@@ -114,6 +114,7 @@
 rm -r -f "$GOMOBILE"
 mkdir -p $GOMOBILE
 WORK={{.GOPATH}}/pkg/gomobile/work
+go install -x golang.org/x/mobile/cmd/gobind
 PWD=$NDK_PATH $NDK_PATH/prebuilt/{{.GOOS}}-{{.NDKARCH}}/bin/python2.7 build/tools/make_standalone_toolchain.py --arch=arm --api=15 --install-dir=$GOMOBILE/ndk-toolchains/arm
 PWD=$NDK_PATH $NDK_PATH/prebuilt/{{.GOOS}}-{{.NDKARCH}}/bin/python2.7 build/tools/make_standalone_toolchain.py --arch=arm64 --api=21 --install-dir=$GOMOBILE/ndk-toolchains/arm64
 PWD=$NDK_PATH $NDK_PATH/prebuilt/{{.GOOS}}-{{.NDKARCH}}/bin/python2.7 build/tools/make_standalone_toolchain.py --arch=x86 --api=15 --install-dir=$GOMOBILE/ndk-toolchains/x86