https://github.com/golang/mobile
-To run the standard library tests, see androidtest.bash. Run it as
+To run the standard library tests, enable Cgo and use an appropriate
+C compiler from the Android NDK. For example,
- CC_FOR_TARGET=$STANDALONE_NDK_PATH/bin/clang GOARCH=arm64 ./androidtest.bash
-
-To create a standalone android NDK tool chain, follow the instructions on
-
- https://developer.android.com/ndk/guides/standalone_toolchain
+ CGO_ENABLED=1 \
+ GOOS=android \
+ GOARCH=arm64 \
+ CC=$NDK/toolchains/llvm/prebuilt/linux-x86_64/bin/aarch64-linux-android21-clang \
+ ./all.bash
To run tests on the Android device, add the bin directory to PATH so the
go tool can find the go_android_$GOARCH_exec wrapper generated by
-androidtest.bash. Then, use the same GOARCH as when androidtest.bash ran
-and set GOOS to android. For example, to run the go1 benchmarks
+make.bash. For example, to run the go1 benchmarks
export PATH=$GOROOT/bin:$PATH
cd $GOROOT/test/bench/go1/
+++ /dev/null
-// 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
-
-// Cleaner removes anything from /data/local/tmp/goroot not on a builtin list.
-// Used by androidtest.bash.
-package main
-
-import (
- "log"
- "os"
- "path/filepath"
- "strings"
-)
-
-func main() {
- const goroot = "/data/local/tmp/goroot"
- expect := make(map[string]bool)
- for _, f := range strings.Split(files, "\n") {
- expect[filepath.Join(goroot, f)] = true
- }
-
- err := filepath.Walk(goroot, func(path string, info os.FileInfo, err error) error {
- if expect[path] {
- return nil
- }
- log.Printf("removing %s", path)
- if err := os.RemoveAll(path); err != nil {
- return err
- }
- if info.IsDir() {
- return filepath.SkipDir
- }
- return nil
- })
- if err != nil {
- log.Fatal(err)
- }
-}
"fmt"
"go/build"
"io"
+ "io/ioutil"
"log"
"os"
"os/exec"
deviceCwd := filepath.Join(deviceGoroot, subdir)
if !inGoRoot {
deviceCwd = filepath.Join(deviceGopath, subdir)
+ } else {
+ adbSyncGoroot()
}
// Binary names can conflict.
cwd, runtime.GOROOT(), build.Default.GOPATH)
return "", false
}
+
+// adbSyncGoroot ensures that files necessary for testing the Go standard
+// packages are present on the attached device.
+func adbSyncGoroot() {
+ // Also known by cmd/dist. The bootstrap command deletes the file.
+ statPath := filepath.Join(os.TempDir(), "go_android_exec-adb-sync-status")
+ stat, err := os.OpenFile(statPath, os.O_CREATE|os.O_RDWR, 0666)
+ if err != nil {
+ log.Fatal(err)
+ }
+ defer stat.Close()
+ // Serialize check and syncing.
+ if err := syscall.Flock(int(stat.Fd()), syscall.LOCK_EX); err != nil {
+ log.Fatal(err)
+ }
+ s, err := ioutil.ReadAll(stat)
+ if err != nil {
+ log.Fatal(err)
+ }
+ if string(s) == "done" {
+ return
+ }
+ devRoot := "/data/local/tmp/goroot"
+ run("shell", "rm", "-rf", devRoot)
+ run("shell", "mkdir", "-p", devRoot+"/pkg")
+ goroot := runtime.GOROOT()
+ goCmd := filepath.Join(goroot, "bin", "go")
+ runtimea, err := exec.Command(goCmd, "list", "-f", "{{.Target}}", "runtime").Output()
+ if err != nil {
+ log.Fatal(err)
+ }
+ pkgdir := filepath.Dir(string(runtimea))
+ if pkgdir == "" {
+ log.Fatal("could not find android pkg dir")
+ }
+ for _, dir := range []string{"src", "test", "lib"} {
+ run("push", filepath.Join(goroot, dir), filepath.Join(devRoot))
+ }
+ run("push", filepath.Join(pkgdir), filepath.Join(devRoot, "pkg/"))
+ if _, err := stat.Write([]byte("done")); err != nil {
+ log.Fatal(err)
+ }
+}
# 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
export CGO_ENABLED=1
unset GOBIN
-# Do the build first, so we can build the 'cleaner' binary.
-# Also lets us fail early before the (slow) adb push if the build is broken.
-. ./make.bash --no-banner
export GOROOT=$(dirname $(pwd))
+# Put the exec wrapper into PATH
export PATH=$GOROOT/bin:$PATH
-export pkgdir=$(dirname $(go list -f '{{.Target}}' runtime))
-if [ "$pkgdir" = "" ]; then
- echo "could not find android pkg dir" 1>&2
- exit 1
-fi
-
-export ANDROID_TEST_DIR=/tmp/androidtest-$$
-
-function cleanup() {
- rm -rf ${ANDROID_TEST_DIR}
-}
-trap cleanup EXIT
-
-# 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. We copy the files required for running tests under
-# /data/local/tmp/goroot. The adb sync command does not follow
-# symlinks so we have to copy.
-export ANDROID_PRODUCT_OUT="${ANDROID_TEST_DIR}/out"
-FAKE_GOROOT=$ANDROID_PRODUCT_OUT/data/local/tmp/goroot
-mkdir -p $FAKE_GOROOT
-mkdir -p $FAKE_GOROOT/pkg
-cp -a "${GOROOT}/src" "${FAKE_GOROOT}/"
-cp -a "${GOROOT}/test" "${FAKE_GOROOT}/"
-cp -a "${GOROOT}/lib" "${FAKE_GOROOT}/"
-cp -a "${pkgdir}" "${FAKE_GOROOT}/pkg/"
-
-echo '# Syncing test files to android device'
-adb $GOANDROID_ADB_FLAGS shell mkdir -p /data/local/tmp/goroot
-time adb $GOANDROID_ADB_FLAGS sync data &> /dev/null
-
-export CLEANER=${ANDROID_TEST_DIR}/androidcleaner-$$
-cp ../misc/android/cleaner.go $CLEANER.go
-echo 'var files = `' >> $CLEANER.go
-(cd $ANDROID_PRODUCT_OUT/data/local/tmp/goroot; find . >> $CLEANER.go)
-echo '`' >> $CLEANER.go
-go build -o $CLEANER $CLEANER.go
-adb $GOANDROID_ADB_FLAGS push $CLEANER /data/local/tmp/cleaner
-adb $GOANDROID_ADB_FLAGS shell /data/local/tmp/cleaner
-
-echo ''
-
# Run standard tests.
-bash run.bash --no-rebuild
+bash all.bash
// Remove go_bootstrap now that we're done.
xremove(pathf("%s/go_bootstrap", tooldir))
- // Build the exec wrapper if necessary.
+ if goos == "android" {
+ // Make sure the exec wrapper will sync a fresh $GOROOT to the device.
+ xremove(pathf("%s/go_android_exec-adb-sync-status", os.TempDir()))
+ }
+
if wrapperPath := wrapperPathFor(goos, goarch); wrapperPath != "" {
oldcc := os.Getenv("CC")
os.Setenv("GOOS", gohostos)