// Copyright 2015 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. // +build ignore // detect attempts to autodetect the correct // values of the environment variables // used by go_darwin_arm_exec. // detect shells out to ideviceinfo, a third party program that can // be obtained by following the instructions at // https://github.com/libimobiledevice/libimobiledevice. package main import ( "bytes" "fmt" "io/ioutil" "os" "os/exec" "strings" ) func main() { devID := detectDevID() fmt.Printf("export GOIOS_DEV_ID=%s\n", devID) udid := detectUDID() mp := detectMobileProvisionFile(udid) f, err := ioutil.TempFile("", "go_ios_detect_") check(err) fname := f.Name() defer os.Remove(fname) out := combinedOutput(parseMobileProvision(mp)) _, err = f.Write(out) check(err) check(f.Close()) appID, err := plistExtract(fname, "ApplicationIdentifierPrefix:0") check(err) fmt.Printf("export GOIOS_APP_ID=%s\n", appID) teamID, err := plistExtract(fname, "Entitlements:com.apple.developer.team-identifier") check(err) fmt.Printf("export GOIOS_TEAM_ID=%s\n", teamID) } func detectDevID() string { cmd := exec.Command("security", "find-identity", "-p", "codesigning", "-v") lines := getLines(cmd) for _, line := range lines { if !bytes.Contains(line, []byte("iPhone Developer")) { continue } if bytes.Contains(line, []byte("REVOKED")) { continue } fields := bytes.Fields(line) return string(fields[1]) } fail("no code signing identity found") panic("unreachable") } var udidPrefix = []byte("UniqueDeviceID: ") func detectUDID() []byte { cmd := exec.Command("ideviceinfo") lines := getLines(cmd) for _, line := range lines { if bytes.HasPrefix(line, udidPrefix) { return bytes.TrimPrefix(line, udidPrefix) } } fail("udid not found; is the device connected?") panic("unreachable") } func detectMobileProvisionFile(udid []byte) string { cmd := exec.Command("mdfind", "-name", ".mobileprovision") lines := getLines(cmd) for _, line := range lines { if len(line) == 0 { continue } xmlLines := getLines(parseMobileProvision(string(line))) for _, xmlLine := range xmlLines { if bytes.Contains(xmlLine, udid) { return string(line) } } } fail("did not find mobile provision matching device udid %s", udid) panic("ureachable") } func parseMobileProvision(fname string) *exec.Cmd { return exec.Command("security", "cms", "-D", "-i", string(fname)) } func plistExtract(fname string, path string) ([]byte, error) { out, err := exec.Command("/usr/libexec/PlistBuddy", "-c", "Print "+path, fname).CombinedOutput() if err != nil { return nil, err } return bytes.TrimSpace(out), nil } func getLines(cmd *exec.Cmd) [][]byte { out := combinedOutput(cmd) return bytes.Split(out, []byte("\n")) } func combinedOutput(cmd *exec.Cmd) []byte { out, err := cmd.CombinedOutput() if err != nil { fmt.Println(strings.Join(cmd.Args, "\n")) fmt.Fprintln(os.Stderr, err) os.Exit(1) } return out } func check(err error) { if err != nil { fail(err.Error()) } } func fail(msg string, v ...interface{}) { fmt.Fprintf(os.Stderr, msg, v...) fmt.Fprintln(os.Stderr) os.Exit(1) }