cmd/gomobile: work around broken Windows NDK compiler scripts

Fixes golang/go#30415

Change-Id: I6cda312f465e05d28601432845c3c3d0f7a85605
Reviewed-on: https://go-review.googlesource.com/c/164177
Run-TryBot: Elias Naur <mail@eliasnaur.com>
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
diff --git a/cmd/gomobile/env.go b/cmd/gomobile/env.go
index 5a523fe..ccdff9b 100644
--- a/cmd/gomobile/env.go
+++ b/cmd/gomobile/env.go
@@ -4,6 +4,7 @@
 	"errors"
 	"fmt"
 	"io/ioutil"
+	"log"
 	"os"
 	"os/exec"
 	"path/filepath"
@@ -46,10 +47,6 @@
 		return nil, errors.New("toolchain not installed, run `gomobile init`")
 	}
 
-	if err := envInit(); err != nil {
-		return nil, err
-	}
-
 	cleanupFn := func() {
 		if buildWork {
 			fmt.Printf("WORK=%s\n", tmpdir)
@@ -70,6 +67,10 @@
 		fmt.Fprintln(xout, "WORK="+tmpdir)
 	}
 
+	if err := envInit(); err != nil {
+		return nil, err
+	}
+
 	return cleanupFn, nil
 }
 
@@ -269,6 +270,9 @@
 	var pref string
 	switch toolName {
 	case "clang", "clang++":
+		if runtime.GOOS == "windows" {
+			return tc.createNDKr19bWorkaroundTool(ndkRoot, toolName)
+		}
 		pref = tc.clangPrefix
 	default:
 		pref = tc.toolPrefix
@@ -276,6 +280,31 @@
 	return filepath.Join(ndkRoot, "toolchains", "llvm", "prebuilt", archNDK(), "bin", pref+"-"+toolName)
 }
 
+// createNDKr19bWorkaroundTool creates a Windows wrapper script for clang or clang++.
+// The scripts included in r19b are broken on Windows: https://github.com/android-ndk/ndk/issues/920.
+// TODO: Remove this when r19c is out; the code inside is hacky and panicky.
+func (tc *ndkToolchain) createNDKr19bWorkaroundTool(ndkRoot, toolName string) string {
+	toolCmd := filepath.Join(tmpdir, fmt.Sprintf("%s-%s.cmd", tc.arch, toolName))
+	tool, err := os.Create(toolCmd)
+	if err != nil {
+		log.Fatal(err)
+	}
+	defer func() {
+		if err := tool.Close(); err != nil {
+			log.Fatal(err)
+		}
+	}()
+	tcBin := filepath.Join(ndkRoot, "toolchains", "llvm", "prebuilt", archNDK(), "bin")
+	// Adapted from the NDK cmd wrappers.
+	toolCmdContent := fmt.Sprintf(`@echo off
+set _BIN_DIR=%s\
+%%_BIN_DIR%%%s.exe --target=%s -fno-addrsig %%*"`, tcBin, toolName, tc.clangPrefix)
+	if _, err = tool.Write([]byte(toolCmdContent)); err != nil {
+		log.Fatal(err)
+	}
+	return toolCmd
+}
+
 type ndkConfig map[string]ndkToolchain // map: GOOS->androidConfig.
 
 func (nc ndkConfig) Toolchain(arch string) ndkToolchain {