cmd/gomobile: disable bitcode on Go 1.13 or older

iOS's bitcode conflicts with headerpad on Go 1.13 or older. This
problem is fixed on Go 1.14.

This CL disables bitcode only on Go 1.13 or older.

Fixes golang/go#32963

Change-Id: Iac9edd56aaf7819288e8f46b9e29d310305acd9d
Reviewed-on: https://go-review.googlesource.com/c/mobile/+/214899
Run-TryBot: Hajime Hoshi <hajimehoshi@gmail.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Hyang-Ah Hana Kim <hyangah@gmail.com>
diff --git a/cmd/gomobile/bind_test.go b/cmd/gomobile/bind_test.go
index ea179b4..ba62b86 100644
--- a/cmd/gomobile/bind_test.go
+++ b/cmd/gomobile/bind_test.go
@@ -67,12 +67,16 @@
 		}
 		got := filepath.ToSlash(buf.String())
 
+		output, err := defaultOutputData()
+		if err != nil {
+			t.Fatal(err)
+		}
 		data := struct {
 			outputData
 			AndroidPlatform string
 			JavaPkg         string
 		}{
-			outputData:      defaultOutputData(),
+			outputData:      output,
 			AndroidPlatform: platform,
 			JavaPkg:         tc.javaPkg,
 		}
@@ -137,12 +141,19 @@
 		}
 		got := filepath.ToSlash(buf.String())
 
+		output, err := defaultOutputData()
+		if err != nil {
+			t.Fatal(err)
+		}
+
 		data := struct {
 			outputData
-			Prefix string
+			Prefix         string
+			BitcodeEnabled bool
 		}{
-			outputData: defaultOutputData(),
-			Prefix:     tc.prefix,
+			outputData:     output,
+			Prefix:         tc.prefix,
+			BitcodeEnabled: bitcodeEnabled,
 		}
 
 		wantBuf := new(bytes.Buffer)
@@ -175,7 +186,7 @@
 WORK=$WORK
 GOOS=darwin CGO_ENABLED=1 gobind -lang=go,objc -outdir=$WORK -tags=ios{{if .Prefix}} -prefix={{.Prefix}}{{end}} golang.org/x/mobile/asset
 mkdir -p $WORK/src
-PWD=$WORK/src GOARM=7 GOOS=darwin GOARCH=arm CC=iphoneos-clang CXX=iphoneos-clang++ CGO_CFLAGS=-isysroot=iphoneos -miphoneos-version-min=7.0 -fembed-bitcode -arch armv7 CGO_CXXFLAGS=-isysroot=iphoneos -miphoneos-version-min=7.0 -fembed-bitcode -arch armv7 CGO_LDFLAGS=-isysroot=iphoneos -miphoneos-version-min=7.0 -fembed-bitcode -arch armv7 CGO_ENABLED=1 GOPATH=$WORK:$GOPATH go build -tags ios -x -buildmode=c-archive -o $WORK/asset-arm.a ./gobind
+PWD=$WORK/src GOARM=7 GOOS=darwin GOARCH=arm CC=iphoneos-clang CXX=iphoneos-clang++ CGO_CFLAGS=-isysroot=iphoneos -miphoneos-version-min=7.0 {{if .BitcodeEnabled}}-fembed-bitcode {{end}}-arch armv7 CGO_CXXFLAGS=-isysroot=iphoneos -miphoneos-version-min=7.0 {{if .BitcodeEnabled}}-fembed-bitcode {{end}}-arch armv7 CGO_LDFLAGS=-isysroot=iphoneos -miphoneos-version-min=7.0 {{if .BitcodeEnabled}}-fembed-bitcode {{end}}-arch armv7 CGO_ENABLED=1 GOPATH=$WORK:$GOPATH go build -tags ios -x -buildmode=c-archive -o $WORK/asset-arm.a ./gobind
 rm -r -f "Asset.framework"
 mkdir -p Asset.framework/Versions/A/Headers
 ln -s A Asset.framework/Versions/Current
diff --git a/cmd/gomobile/build_darwin_test.go b/cmd/gomobile/build_darwin_test.go
index ce760a3..cfe42c9 100644
--- a/cmd/gomobile/build_darwin_test.go
+++ b/cmd/gomobile/build_darwin_test.go
@@ -55,16 +55,23 @@
 			t.Fatalf("detecting team ID failed: %v", err)
 		}
 
+		output, err := defaultOutputData()
+		if err != nil {
+			t.Fatal(err)
+		}
+
 		data := struct {
 			outputData
-			TeamID string
-			Pkg    string
-			Main   bool
+			TeamID         string
+			Pkg            string
+			Main           bool
+			BitcodeEnabled bool
 		}{
-			outputData: defaultOutputData(),
-			TeamID:     teamID,
-			Pkg:        test.pkg,
-			Main:       test.main,
+			outputData:     output,
+			TeamID:         teamID,
+			Pkg:            test.pkg,
+			Main:           test.main,
+			BitcodeEnabled: bitcodeEnabled,
 		}
 
 		got := filepath.ToSlash(buf.String())
@@ -94,10 +101,10 @@
 echo "{{template "infoplist" .Xinfo}}" > $WORK/main/Info.plist
 mkdir -p $WORK/main/Images.xcassets/AppIcon.appiconset
 echo "{{.Xcontents}}" > $WORK/main/Images.xcassets/AppIcon.appiconset/Contents.json{{end}}
-GOARM=7 GOOS=darwin GOARCH=arm CC=iphoneos-clang CXX=iphoneos-clang++ CGO_CFLAGS=-isysroot=iphoneos -miphoneos-version-min=7.0 -fembed-bitcode -arch armv7 CGO_CXXFLAGS=-isysroot=iphoneos -miphoneos-version-min=7.0 -fembed-bitcode -arch armv7 CGO_LDFLAGS=-isysroot=iphoneos -miphoneos-version-min=7.0 -fembed-bitcode -arch armv7 CGO_ENABLED=1 go build -tags tag1 ios -x {{if .Main}}-ldflags=-w -o=$WORK/arm {{end}}{{.Pkg}}
-GOOS=darwin GOARCH=arm64 CC=iphoneos-clang CXX=iphoneos-clang++ CGO_CFLAGS=-isysroot=iphoneos -miphoneos-version-min=7.0 -fembed-bitcode -arch arm64 CGO_CXXFLAGS=-isysroot=iphoneos -miphoneos-version-min=7.0 -fembed-bitcode -arch arm64 CGO_LDFLAGS=-isysroot=iphoneos -miphoneos-version-min=7.0 -fembed-bitcode -arch arm64 CGO_ENABLED=1 go build -tags tag1 ios -x {{if .Main}}-ldflags=-w -o=$WORK/arm64 {{end}}{{.Pkg}}
-GOOS=darwin GOARCH=386 CC=iphonesimulator-clang CXX=iphonesimulator-clang++ CGO_CFLAGS=-isysroot=iphonesimulator -mios-simulator-version-min=7.0 -fembed-bitcode -arch i386 CGO_CXXFLAGS=-isysroot=iphonesimulator -mios-simulator-version-min=7.0 -fembed-bitcode -arch i386 CGO_LDFLAGS=-isysroot=iphonesimulator -mios-simulator-version-min=7.0 -fembed-bitcode -arch i386 CGO_ENABLED=1 go build -tags tag1 ios -x {{if .Main}}-ldflags=-w -o=$WORK/386 {{end}}{{.Pkg}}
-GOOS=darwin GOARCH=amd64 CC=iphonesimulator-clang CXX=iphonesimulator-clang++ CGO_CFLAGS=-isysroot=iphonesimulator -mios-simulator-version-min=7.0 -fembed-bitcode -arch x86_64 CGO_CXXFLAGS=-isysroot=iphonesimulator -mios-simulator-version-min=7.0 -fembed-bitcode -arch x86_64 CGO_LDFLAGS=-isysroot=iphonesimulator -mios-simulator-version-min=7.0 -fembed-bitcode -arch x86_64 CGO_ENABLED=1 go build -tags tag1 ios -x {{if .Main}}-ldflags=-w -o=$WORK/amd64 {{end}}{{.Pkg}}{{if .Main}}
+GOARM=7 GOOS=darwin GOARCH=arm CC=iphoneos-clang CXX=iphoneos-clang++ CGO_CFLAGS=-isysroot=iphoneos -miphoneos-version-min=7.0 {{if .BitcodeEnabled}}-fembed-bitcode {{end}}-arch armv7 CGO_CXXFLAGS=-isysroot=iphoneos -miphoneos-version-min=7.0 {{if .BitcodeEnabled}}-fembed-bitcode {{end}}-arch armv7 CGO_LDFLAGS=-isysroot=iphoneos -miphoneos-version-min=7.0 {{if .BitcodeEnabled}}-fembed-bitcode {{end}}-arch armv7 CGO_ENABLED=1 go build -tags tag1 ios -x {{if .Main}}-ldflags=-w -o=$WORK/arm {{end}}{{.Pkg}}
+GOOS=darwin GOARCH=arm64 CC=iphoneos-clang CXX=iphoneos-clang++ CGO_CFLAGS=-isysroot=iphoneos -miphoneos-version-min=7.0 {{if .BitcodeEnabled}}-fembed-bitcode {{end}}-arch arm64 CGO_CXXFLAGS=-isysroot=iphoneos -miphoneos-version-min=7.0 {{if .BitcodeEnabled}}-fembed-bitcode {{end}}-arch arm64 CGO_LDFLAGS=-isysroot=iphoneos -miphoneos-version-min=7.0 {{if .BitcodeEnabled}}-fembed-bitcode {{end}}-arch arm64 CGO_ENABLED=1 go build -tags tag1 ios -x {{if .Main}}-ldflags=-w -o=$WORK/arm64 {{end}}{{.Pkg}}
+GOOS=darwin GOARCH=386 CC=iphonesimulator-clang CXX=iphonesimulator-clang++ CGO_CFLAGS=-isysroot=iphonesimulator -mios-simulator-version-min=7.0 {{if .BitcodeEnabled}}-fembed-bitcode {{end}}-arch i386 CGO_CXXFLAGS=-isysroot=iphonesimulator -mios-simulator-version-min=7.0 {{if .BitcodeEnabled}}-fembed-bitcode {{end}}-arch i386 CGO_LDFLAGS=-isysroot=iphonesimulator -mios-simulator-version-min=7.0 {{if .BitcodeEnabled}}-fembed-bitcode {{end}}-arch i386 CGO_ENABLED=1 go build -tags tag1 ios -x {{if .Main}}-ldflags=-w -o=$WORK/386 {{end}}{{.Pkg}}
+GOOS=darwin GOARCH=amd64 CC=iphonesimulator-clang CXX=iphonesimulator-clang++ CGO_CFLAGS=-isysroot=iphonesimulator -mios-simulator-version-min=7.0 {{if .BitcodeEnabled}}-fembed-bitcode {{end}}-arch x86_64 CGO_CXXFLAGS=-isysroot=iphonesimulator -mios-simulator-version-min=7.0 {{if .BitcodeEnabled}}-fembed-bitcode {{end}}-arch x86_64 CGO_LDFLAGS=-isysroot=iphonesimulator -mios-simulator-version-min=7.0 {{if .BitcodeEnabled}}-fembed-bitcode {{end}}-arch x86_64 CGO_ENABLED=1 go build -tags tag1 ios -x {{if .Main}}-ldflags=-w -o=$WORK/amd64 {{end}}{{.Pkg}}{{if .Main}}
 xcrun lipo -o $WORK/main/main -create $WORK/arm $WORK/arm64 $WORK/386 $WORK/amd64
 mkdir -p $WORK/main/assets
 xcrun xcodebuild -configuration Release -project $WORK/main.xcodeproj -allowProvisioningUpdates DEVELOPMENT_TEAM={{.TeamID}}
diff --git a/cmd/gomobile/build_iosapp.go b/cmd/gomobile/build_iosapp.go
index a0103de..67fe3b5 100644
--- a/cmd/gomobile/build_iosapp.go
+++ b/cmd/gomobile/build_iosapp.go
@@ -31,6 +31,13 @@
 		productName = "ProductName" // like xcode.
 	}
 
+	projPbxproj := new(bytes.Buffer)
+	if err := projPbxprojTmpl.Execute(projPbxproj, projPbxprojTmplData{
+		BitcodeEnabled: bitcodeEnabled,
+	}); err != nil {
+		return nil, err
+	}
+
 	infoplist := new(bytes.Buffer)
 	if err := infoplistTmpl.Execute(infoplist, infoplistTmplData{
 		// TODO: better bundle id.
@@ -44,7 +51,7 @@
 		name     string
 		contents []byte
 	}{
-		{tmpdir + "/main.xcodeproj/project.pbxproj", []byte(projPbxproj)},
+		{tmpdir + "/main.xcodeproj/project.pbxproj", projPbxproj.Bytes()},
 		{tmpdir + "/main/Info.plist", infoplist.Bytes()},
 		{tmpdir + "/main/Images.xcassets/AppIcon.appiconset/Contents.json", []byte(contentsJSON)},
 	}
@@ -271,7 +278,11 @@
 </plist>
 `))
 
-const projPbxproj = `// !$*UTF8*$!
+type projPbxprojTmplData struct {
+	BitcodeEnabled bool
+}
+
+var projPbxprojTmpl = template.Must(template.New("projPbxproj").Parse(`// !$*UTF8*$!
 {
   archiveVersion = 1;
   classes = {
@@ -429,6 +440,7 @@
         SDKROOT = iphoneos;
         TARGETED_DEVICE_FAMILY = "1,2";
         VALIDATE_PRODUCT = YES;
+        {{if not .BitcodeEnabled}}ENABLE_BITCODE = NO;{{end}}
       };
       name = Release;
     };
@@ -465,7 +477,7 @@
   };
   rootObject = 254BB8361B1FD08900C56DE9 /* Project object */;
 }
-`
+`))
 
 const contentsJSON = `{
   "images" : [
diff --git a/cmd/gomobile/env.go b/cmd/gomobile/env.go
index d36a418..e6f9b9f 100644
--- a/cmd/gomobile/env.go
+++ b/cmd/gomobile/env.go
@@ -23,6 +23,8 @@
 	darwinArmNM  string
 
 	allArchs = []string{"arm", "arm64", "386", "amd64"}
+
+	bitcodeEnabled bool
 )
 
 func buildEnvInit() (cleanup func(), err error) {
@@ -73,6 +75,15 @@
 }
 
 func envInit() (err error) {
+	// Check the current Go version by go-list.
+	out, err := exec.Command("go", "list", "-e", "-f", `{{range context.ReleaseTags}}{{if eq . "go1.14"}}{{.}}{{end}}{{end}}`).Output()
+	if err != nil {
+		return err
+	}
+	if len(strings.TrimSpace(string(out))) > 0 {
+		bitcodeEnabled = true
+	}
+
 	// Setup the cross-compiler environments.
 	if ndkRoot, err := ndkRoot(); err == nil {
 		androidEnv = make(map[string][]string)
@@ -133,10 +144,13 @@
 		default:
 			panic(fmt.Errorf("unknown GOARCH: %q", arch))
 		}
-		cflags += " -fembed-bitcode"
 		if err != nil {
 			return err
 		}
+
+		if bitcodeEnabled {
+			cflags += " -fembed-bitcode"
+		}
 		env = append(env,
 			"GOOS=darwin",
 			"GOARCH="+arch,
diff --git a/cmd/gomobile/init_test.go b/cmd/gomobile/init_test.go
index 42a8a5a..2330f19 100644
--- a/cmd/gomobile/init_test.go
+++ b/cmd/gomobile/init_test.go
@@ -6,6 +6,7 @@
 
 import (
 	"bytes"
+	"io/ioutil"
 	"os"
 	"os/exec"
 	"path/filepath"
@@ -33,7 +34,11 @@
 	buildX = true
 
 	// Test that first GOPATH element is chosen correctly.
-	gopath = "/GOPATH1"
+	var err error
+	gopath, err = ioutil.TempDir("", "gomobile-test")
+	if err != nil {
+		t.Fatal(err)
+	}
 	paths := []string{gopath, "/path2", "/path3"}
 	if goos == "windows" {
 		gopath = filepath.ToSlash(`C:\GOPATH1`)
@@ -45,8 +50,7 @@
 		os.Setenv("HOMEDRIVE", "C:")
 	}
 
-	err := runInit(cmdInit)
-	if err != nil {
+	if err := runInit(cmdInit); err != nil {
 		t.Log(buf.String())
 		t.Fatal(err)
 	}
@@ -64,7 +68,10 @@
 	got = filepath.ToSlash(got)
 
 	wantBuf := new(bytes.Buffer)
-	data := defaultOutputData()
+	data, err := defaultOutputData()
+	if err != nil {
+		return "", err
+	}
 	if err := wantTmpl.Execute(wantBuf, data); err != nil {
 		return "", err
 	}
@@ -86,20 +93,27 @@
 	Xinfo     infoplistTmplData
 }
 
-func defaultOutputData() outputData {
+func defaultOutputData() (outputData, error) {
+	projPbxproj := new(bytes.Buffer)
+	if err := projPbxprojTmpl.Execute(projPbxproj, projPbxprojTmplData{
+		BitcodeEnabled: bitcodeEnabled,
+	}); err != nil {
+		return outputData{}, err
+	}
+
 	data := outputData{
 		GOOS:      goos,
 		GOARCH:    goarch,
 		GOPATH:    gopath,
 		NDKARCH:   archNDK(),
-		Xproj:     projPbxproj,
+		Xproj:     string(projPbxproj.Bytes()),
 		Xcontents: contentsJSON,
 		Xinfo:     infoplistTmplData{BundleID: "org.golang.todo.basic", Name: "Basic"},
 	}
 	if goos == "windows" {
 		data.EXE = ".exe"
 	}
-	return data
+	return data, nil
 }
 
 var initTmpl = template.Must(template.New("output").Parse(`GOMOBILE={{.GOPATH}}/pkg/gomobile