Skip to content

Commit a5f8e8f

Browse files
committed
androidtest.bash, misc/android: build scripts for android
LGTM=minux R=minux CC=golang-codereviews https://golang.org/cl/107640044
1 parent 29aac3d commit a5f8e8f

File tree

3 files changed

+161
-0
lines changed

3 files changed

+161
-0
lines changed

misc/android/README

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
Android
2+
=======
3+
4+
For details on developing Go for Android, see the documentation in the
5+
go.mobile subrepository:
6+
7+
https://code.google.com/p/go/source/browse/README?repo=mobile
8+
9+
To run the standard library tests, see androidtest.bash. Run it as
10+
11+
CC_FOR_TARGET=.../ndk-gcc GOARCH=arm GOARM=7 ./androidtest.bash

misc/android/go_android_exec.go

Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
// Copyright 2014 The Go Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style
3+
// license that can be found in the LICENSE file.
4+
5+
// This program can be used as go_android_GOARCH_exec by the Go tool.
6+
// It executes binaries on an android device using adb.
7+
package main
8+
9+
import (
10+
"bytes"
11+
"fmt"
12+
"io"
13+
"log"
14+
"os"
15+
"os/exec"
16+
"path/filepath"
17+
"runtime"
18+
"strconv"
19+
"strings"
20+
)
21+
22+
func run(args ...string) string {
23+
buf := new(bytes.Buffer)
24+
cmd := exec.Command("adb", args...)
25+
cmd.Stdout = io.MultiWriter(os.Stdout, buf)
26+
cmd.Stderr = os.Stderr
27+
log.Printf("adb %s", strings.Join(args, " "))
28+
err := cmd.Run()
29+
if err != nil {
30+
log.Fatalf("adb %s: %v", strings.Join(args, " "), err)
31+
}
32+
return buf.String()
33+
}
34+
35+
func main() {
36+
log.SetFlags(0)
37+
log.SetPrefix("go_android_exec: ")
38+
39+
// Determine thepackage by examining the current working
40+
// directory, which will look something like
41+
// "$GOROOT/src/pkg/mime/multipart". We extract everything
42+
// after the $GOROOT to run on the same relative directory
43+
// on the target device.
44+
//
45+
// TODO(crawshaw): Pick useful subdir when we are not
46+
// inside a GOROOT, e.g. we are in a GOPATH.
47+
cwd, err := os.Getwd()
48+
if err != nil {
49+
log.Fatal(err)
50+
}
51+
subdir, err := filepath.Rel(runtime.GOROOT(), cwd)
52+
if err != nil {
53+
log.Fatal(err)
54+
}
55+
subdir = filepath.ToSlash(subdir)
56+
57+
// Binary names can conflict.
58+
// E.g. template.test from the {html,text}/template packages.
59+
binName := filepath.Base(os.Args[1])
60+
deviceGoroot := "/data/local/tmp/goroot"
61+
deviceBin := fmt.Sprintf("%s/%s-%d", deviceGoroot, binName, os.Getpid())
62+
63+
// The push of the binary happens in parallel with other tests.
64+
// Unfortunately, a simultaneous call to adb shell hold open
65+
// file descriptors, so it is necessary to push then move to
66+
// avoid a "text file busy" error on execution.
67+
// https://code.google.com/p/android/issues/detail?id=65857
68+
run("push", os.Args[1], deviceBin+"-tmp")
69+
run("shell", "cp '"+deviceBin+"-tmp' '"+deviceBin+"'")
70+
run("shell", "rm '"+deviceBin+"-tmp'")
71+
72+
// The adb shell command will return an exit code of 0 regardless
73+
// of the command run. E.g.
74+
// $ adb shell false
75+
// $ echo $?
76+
// 0
77+
// https://code.google.com/p/android/issues/detail?id=3254
78+
// So we append the exitcode to the output and parse it from there.
79+
const exitstr = "exitcode="
80+
cmd := `export TMPDIR="/data/local/tmp"` +
81+
`; export GOROOT="` + deviceGoroot + `"` +
82+
`; cd "$GOROOT/` + subdir + `"` +
83+
"; '" + deviceBin + "' " + strings.Join(os.Args[2:], " ") +
84+
"; echo -n " + exitstr + "$?"
85+
output := run("shell", cmd)
86+
run("shell", "rm '"+deviceBin+"'") // cleanup
87+
output = output[strings.LastIndex(output, "\n")+1:]
88+
if !strings.HasPrefix(output, exitstr) {
89+
log.Fatalf("no exit code: %q", output)
90+
}
91+
code, err := strconv.Atoi(output[len(exitstr):])
92+
if err != nil {
93+
log.Fatalf("bad exit code: %v", err)
94+
}
95+
os.Exit(code)
96+
}

src/androidtest.bash

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
#/usr/bin/env bash
2+
# Copyright 2014 The Go Authors. All rights reserved.
3+
# Use of this source code is governed by a BSD-style
4+
# license that can be found in the LICENSE file.
5+
6+
# For testing Android.
7+
# The compiler runs locally, then a copy of the GOROOT is pushed to a
8+
# target device using adb, and the tests are run there.
9+
10+
set -e
11+
ulimit -c 0 # no core files
12+
13+
if [ ! -f make.bash ]; then
14+
echo 'nacl.bash must be run from $GOROOT/src' 1>&2
15+
exit 1
16+
fi
17+
18+
if [ -z $GOOS ]; then
19+
export GOOS=android
20+
fi
21+
if [ "$GOOS" != "android" ]; then
22+
echo "androidtest.bash requires GOOS=android, got GOOS=$GOOS" 1>&2
23+
exit 1
24+
fi
25+
26+
export CGO_ENABLED=1
27+
28+
# Run the build for the host bootstrap, so we can build go_android_exec.
29+
# Also lets us fail early before the (slow) adb push if the build is broken.
30+
./make.bash
31+
export GOROOT=$(dirname $(pwd))
32+
export PATH=$GOROOT/bin:$PATH
33+
GOOS=$GOHOSTOS GOARCH=$GOHOSTARCH go build \
34+
-o ../bin/go_android_${GOARCH}_exec \
35+
../misc/android/go_android_exec.go
36+
37+
# Push GOROOT to target device.
38+
#
39+
# The adb sync command will sync either the /system or /data
40+
# directories of an android device from a similar directory
41+
# on the host. So we fake one with symlinks to push the GOROOT
42+
# into a subdirectory of /data.
43+
export ANDROID_PRODUCT_OUT=/tmp/androidtest-$$
44+
FAKE_GOROOT=$ANDROID_PRODUCT_OUT/data/local/tmp/goroot
45+
mkdir -p $FAKE_GOROOT/src
46+
ln -s $GOROOT/src/cmd $FAKE_GOROOT/src/cmd
47+
ln -s $GOROOT/src/pkg $FAKE_GOROOT/src/pkg
48+
ln -s $GOROOT/test $FAKE_GOROOT/test
49+
ln -s $GOROOT/lib $FAKE_GOROOT/lib
50+
adb sync data
51+
rm -rf "$ANDROID_PRODUCT_OUT"
52+
53+
# Run standard build and tests.
54+
./all.bash --no-clean

0 commit comments

Comments
 (0)