]> Cypherpunks repositories - gostls13.git/commitdiff
androidtest.bash, misc/android: build scripts for android
authorDavid Crawshaw <david.crawshaw@zentus.com>
Wed, 9 Jul 2014 10:56:49 +0000 (06:56 -0400)
committerDavid Crawshaw <david.crawshaw@zentus.com>
Wed, 9 Jul 2014 10:56:49 +0000 (06:56 -0400)
LGTM=minux
R=minux
CC=golang-codereviews
https://golang.org/cl/107640044

misc/android/README [new file with mode: 0644]
misc/android/go_android_exec.go [new file with mode: 0644]
src/androidtest.bash [new file with mode: 0755]

diff --git a/misc/android/README b/misc/android/README
new file mode 100644 (file)
index 0000000..5f24faf
--- /dev/null
@@ -0,0 +1,11 @@
+Android
+=======
+
+For details on developing Go for Android, see the documentation in the
+go.mobile subrepository:
+
+       https://code.google.com/p/go/source/browse/README?repo=mobile
+
+To run the standard library tests, see androidtest.bash. Run it as
+
+       CC_FOR_TARGET=.../ndk-gcc GOARCH=arm GOARM=7 ./androidtest.bash
diff --git a/misc/android/go_android_exec.go b/misc/android/go_android_exec.go
new file mode 100644 (file)
index 0000000..065b624
--- /dev/null
@@ -0,0 +1,96 @@
+// Copyright 2014 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.
+
+// This program can be used as go_android_GOARCH_exec by the Go tool.
+// It executes binaries on an android device using adb.
+package main
+
+import (
+       "bytes"
+       "fmt"
+       "io"
+       "log"
+       "os"
+       "os/exec"
+       "path/filepath"
+       "runtime"
+       "strconv"
+       "strings"
+)
+
+func run(args ...string) string {
+       buf := new(bytes.Buffer)
+       cmd := exec.Command("adb", args...)
+       cmd.Stdout = io.MultiWriter(os.Stdout, buf)
+       cmd.Stderr = os.Stderr
+       log.Printf("adb %s", strings.Join(args, " "))
+       err := cmd.Run()
+       if err != nil {
+               log.Fatalf("adb %s: %v", strings.Join(args, " "), err)
+       }
+       return buf.String()
+}
+
+func main() {
+       log.SetFlags(0)
+       log.SetPrefix("go_android_exec: ")
+
+       // Determine thepackage by examining the current working
+       // directory, which will look something like
+       // "$GOROOT/src/pkg/mime/multipart". We extract everything
+       // after the $GOROOT to run on the same relative directory
+       // on the target device.
+       //
+       // TODO(crawshaw): Pick useful subdir when we are not
+       // inside a GOROOT, e.g. we are in a GOPATH.
+       cwd, err := os.Getwd()
+       if err != nil {
+               log.Fatal(err)
+       }
+       subdir, err := filepath.Rel(runtime.GOROOT(), cwd)
+       if err != nil {
+               log.Fatal(err)
+       }
+       subdir = filepath.ToSlash(subdir)
+
+       // Binary names can conflict.
+       // E.g. template.test from the {html,text}/template packages.
+       binName := filepath.Base(os.Args[1])
+       deviceGoroot := "/data/local/tmp/goroot"
+       deviceBin := fmt.Sprintf("%s/%s-%d", deviceGoroot, binName, os.Getpid())
+
+       // The push of the binary happens in parallel with other tests.
+       // Unfortunately, a simultaneous call to adb shell hold open
+       // file descriptors, so it is necessary to push then move to
+       // avoid a "text file busy" error on execution.
+       // https://code.google.com/p/android/issues/detail?id=65857
+       run("push", os.Args[1], deviceBin+"-tmp")
+       run("shell", "cp '"+deviceBin+"-tmp' '"+deviceBin+"'")
+       run("shell", "rm '"+deviceBin+"-tmp'")
+
+       // The adb shell command will return an exit code of 0 regardless
+       // of the command run. E.g.
+       //      $ adb shell false
+       //      $ echo $?
+       //      0
+       // https://code.google.com/p/android/issues/detail?id=3254
+       // So we append the exitcode to the output and parse it from there.
+       const exitstr = "exitcode="
+       cmd := `export TMPDIR="/data/local/tmp"` +
+               `; export GOROOT="` + deviceGoroot + `"` +
+               `; cd "$GOROOT/` + subdir + `"` +
+               "; '" + deviceBin + "' " + strings.Join(os.Args[2:], " ") +
+               "; echo -n " + exitstr + "$?"
+       output := run("shell", cmd)
+       run("shell", "rm '"+deviceBin+"'") // cleanup
+       output = output[strings.LastIndex(output, "\n")+1:]
+       if !strings.HasPrefix(output, exitstr) {
+               log.Fatalf("no exit code: %q", output)
+       }
+       code, err := strconv.Atoi(output[len(exitstr):])
+       if err != nil {
+               log.Fatalf("bad exit code: %v", err)
+       }
+       os.Exit(code)
+}
diff --git a/src/androidtest.bash b/src/androidtest.bash
new file mode 100755 (executable)
index 0000000..ede085e
--- /dev/null
@@ -0,0 +1,54 @@
+#/usr/bin/env bash
+# Copyright 2014 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.
+
+# For testing Android.
+# The compiler runs locally, then a copy of the GOROOT is pushed to a
+# target device using adb, and the tests are run there.
+
+set -e
+ulimit -c 0 # no core files
+
+if [ ! -f make.bash ]; then
+       echo 'nacl.bash must be run from $GOROOT/src' 1>&2
+       exit 1
+fi
+
+if [ -z $GOOS ]; then
+       export GOOS=android
+fi
+if [ "$GOOS" != "android" ]; then
+       echo "androidtest.bash requires GOOS=android, got GOOS=$GOOS" 1>&2
+       exit 1
+fi
+
+export CGO_ENABLED=1
+
+# Run the build for the host bootstrap, so we can build go_android_exec.
+# Also lets us fail early before the (slow) adb push if the build is broken.
+./make.bash
+export GOROOT=$(dirname $(pwd))
+export PATH=$GOROOT/bin:$PATH
+GOOS=$GOHOSTOS GOARCH=$GOHOSTARCH go build \
+       -o ../bin/go_android_${GOARCH}_exec \
+       ../misc/android/go_android_exec.go
+
+# Push GOROOT to target device.
+#
+# The adb sync command will sync either the /system or /data
+# directories of an android device from a similar directory
+# on the host. So we fake one with symlinks to push the GOROOT
+# into a subdirectory of /data.
+export ANDROID_PRODUCT_OUT=/tmp/androidtest-$$
+FAKE_GOROOT=$ANDROID_PRODUCT_OUT/data/local/tmp/goroot
+mkdir -p $FAKE_GOROOT/src
+ln -s $GOROOT/src/cmd $FAKE_GOROOT/src/cmd
+ln -s $GOROOT/src/pkg $FAKE_GOROOT/src/pkg
+ln -s $GOROOT/test $FAKE_GOROOT/test
+ln -s $GOROOT/lib $FAKE_GOROOT/lib
+adb sync data
+rm -rf "$ANDROID_PRODUCT_OUT"
+
+# Run standard build and tests.
+./all.bash --no-clean