cmd/gomobile: embed teamID into Xcode project settings

The default Xcode project settings do not specify any team ID.
If we open the Xcode project in Xcode, it won't compile and deploy
the app directly via Xcode unless a user manually selects the team
account. This is an extra effort. Since we can detect team ID
automatically embeds the teamID directly into the project settings
so it better helps the user to compile and deploy apps without getting
into the project settings.

Change-Id: I268653f66280bb6cf013f0a28891e4382e4de576
Reviewed-on: https://go-review.googlesource.com/c/mobile/+/351409
Run-TryBot: Hajime Hoshi <hajimehoshi@gmail.com>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Hajime Hoshi <hajimehoshi@gmail.com>
Trust: Hajime Hoshi <hajimehoshi@gmail.com>
Trust: Hyang-Ah Hana Kim <hyangah@gmail.com>
diff --git a/cmd/gomobile/bind_test.go b/cmd/gomobile/bind_test.go
index 5970c04..0e9f401 100644
--- a/cmd/gomobile/bind_test.go
+++ b/cmd/gomobile/bind_test.go
@@ -67,7 +67,7 @@
 		}
 		got := filepath.ToSlash(buf.String())
 
-		output, err := defaultOutputData()
+		output, err := defaultOutputData("")
 		if err != nil {
 			t.Fatal(err)
 		}
@@ -148,7 +148,7 @@
 		}
 		got := filepath.ToSlash(buf.String())
 
-		output, err := defaultOutputData()
+		output, err := defaultOutputData("")
 		if err != nil {
 			t.Fatal(err)
 		}
diff --git a/cmd/gomobile/build_apple.go b/cmd/gomobile/build_apple.go
index 2adaf3d..9ec2056 100644
--- a/cmd/gomobile/build_apple.go
+++ b/cmd/gomobile/build_apple.go
@@ -40,11 +40,24 @@
 		return nil, err
 	}
 
+	// Detect the team ID
+	teamID, err := detectTeamID()
+	if err != nil {
+		return nil, err
+	}
+
+	projPbxproj := new(bytes.Buffer)
+	if err := projPbxprojTmpl.Execute(projPbxproj, projPbxprojTmplData{
+		TeamID: teamID,
+	}); err != nil {
+		return nil, err
+	}
+
 	files := []struct {
 		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)},
 	}
@@ -106,12 +119,6 @@
 		return nil, err
 	}
 
-	// Detect the team ID
-	teamID, err := detectTeamID()
-	if err != nil {
-		return nil, err
-	}
-
 	// Build and move the release build to the output directory.
 	cmdStrings := []string{
 		"xcodebuild",
@@ -282,7 +289,11 @@
 </plist>
 `))
 
-const projPbxproj = `// !$*UTF8*$!
+type projPbxprojTmplData struct {
+	TeamID string
+}
+
+var projPbxprojTmpl = template.Must(template.New("projPbxproj").Parse(`// !$*UTF8*$!
 {
   archiveVersion = 1;
   classes = {
@@ -370,6 +381,7 @@
         TargetAttributes = {
           254BB83D1B1FD08900C56DE9 = {
             CreatedOnToolsVersion = 6.3.1;
+            DevelopmentTeam = {{.TeamID}};
           };
         };
       };
@@ -476,7 +488,7 @@
   };
   rootObject = 254BB8361B1FD08900C56DE9 /* Project object */;
 }
-`
+`))
 
 const contentsJSON = `{
   "images" : [
diff --git a/cmd/gomobile/build_darwin_test.go b/cmd/gomobile/build_darwin_test.go
index 2fac27c..bb87701 100644
--- a/cmd/gomobile/build_darwin_test.go
+++ b/cmd/gomobile/build_darwin_test.go
@@ -61,7 +61,7 @@
 			t.Fatalf("detecting team ID failed: %v", err)
 		}
 
-		output, err := defaultOutputData()
+		output, err := defaultOutputData(teamID)
 		if err != nil {
 			t.Fatal(err)
 		}
diff --git a/cmd/gomobile/init_test.go b/cmd/gomobile/init_test.go
index ee48513..4dfc706 100644
--- a/cmd/gomobile/init_test.go
+++ b/cmd/gomobile/init_test.go
@@ -123,7 +123,7 @@
 	got = filepath.ToSlash(got)
 
 	wantBuf := new(bytes.Buffer)
-	data, err := defaultOutputData()
+	data, err := defaultOutputData("")
 	if err != nil {
 		return "", err
 	}
@@ -148,13 +148,20 @@
 	Xinfo     infoplistTmplData
 }
 
-func defaultOutputData() (outputData, error) {
+func defaultOutputData(teamID string) (outputData, error) {
+	projPbxproj := new(bytes.Buffer)
+	if err := projPbxprojTmpl.Execute(projPbxproj, projPbxprojTmplData{
+		TeamID: teamID,
+	}); err != nil {
+		return outputData{}, err
+	}
+
 	data := outputData{
 		GOOS:      goos,
 		GOARCH:    goarch,
 		GOPATH:    gopath,
 		NDKARCH:   archNDK(),
-		Xproj:     projPbxproj,
+		Xproj:     projPbxproj.String(),
 		Xcontents: contentsJSON,
 		Xinfo:     infoplistTmplData{BundleID: "org.golang.todo.basic", Name: "Basic"},
 	}