app: call main.main on app startup

There is some cleanup to be done in this package now, but I'm
deferring it until later in the cycle.

We should probably also change the semantics slightly: main should
be called for all-Go apps (that is, apps that use NativeActivity),
but it would be more consistent with buildmode=c-shared and c-archive
if we did not call main for Go shared libraries being included in
Java android apps.

Change-Id: I13ca797a478edb22b0c602c1ee6e616fe4fea1e6
Reviewed-on: https://go-review.googlesource.com/9016
Reviewed-by: Hyang-Ah Hana Kim <hyangah@gmail.com>
This commit is contained in:
David Crawshaw 2015-04-17 08:05:20 -04:00
parent 47553f4d42
commit d77bba0a9f
4 changed files with 42 additions and 28 deletions

View File

@ -19,9 +19,6 @@
#define LOG_INFO(...) __android_log_print(ANDROID_LOG_INFO, "Go", __VA_ARGS__)
#define LOG_FATAL(...) __android_log_print(ANDROID_LOG_FATAL, "Go", __VA_ARGS__)
// Defined in the Go runtime.
static int (*_rt0_arm_linux1)(int argc, char** argv);
jint JNI_OnLoad(JavaVM* vm, void* reserved) {
current_vm = vm;
current_ctx = NULL;
@ -122,32 +119,11 @@ static const char* getenv_raw(const char *name) {
static void* init_go_runtime(void* unused) {
init_from_context();
_rt0_arm_linux1 = (int (*)(int, char**))dlsym(RTLD_DEFAULT, "_rt0_arm_linux1");
if (_rt0_arm_linux1 == NULL) {
LOG_FATAL("missing _rt0_arm_linux1");
uintptr_t mainPC = (uintptr_t)dlsym(RTLD_DEFAULT, "main.main");
if (!mainPC) {
LOG_FATAL("missing main.main");
}
// Defensively heap-allocate argv0, for setenv.
char* argv0 = strdup("gojni");
// Build argv, including the ELF auxiliary vector.
struct {
char* argv[2];
const char* envp[4];
uint32_t auxv[64];
} x;
x.argv[0] = argv0;
x.argv[1] = NULL;
x.envp[0] = getenv_raw("TMPDIR=");
x.envp[1] = getenv_raw("PATH=");
x.envp[2] = getenv_raw("LD_LIBRARY_PATH=");
x.envp[3] = NULL;
build_auxv(x.auxv, sizeof(x.auxv)/sizeof(uint32_t));
int32_t argc = 1;
_rt0_arm_linux1(argc, x.argv);
return NULL;
callMain(mainPC);
}
static void wait_go_runtime() {

View File

@ -69,9 +69,20 @@ import (
"runtime"
"unsafe"
"golang.org/x/mobile/app/internal/callfn"
"golang.org/x/mobile/geom"
)
//export callMain
func callMain(mainPC uintptr) {
for _, name := range []string{"TMPDIR", "PATH", "LD_LIBRARY_PATH"} {
n := C.CString(name)
os.Setenv(name, C.GoString(C.getenv(n)))
C.free(unsafe.Pointer(n))
}
callfn.CallFn(mainPC)
}
//export onCreate
func onCreate(activity *C.ANativeActivity) {
C.asset_manager = activity.assetManager

View File

@ -0,0 +1,16 @@
// 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 android,arm
// Package callfn provides an android entry point.
//
// It is a separate package from app because it contains Go assembly,
// which does not compile in a package using cgo.
package callfn
// CallFn calls a zero-argument function by its program counter.
// It is only intended for calling main.main. Using it for
// anything else will not end well.
func CallFn(fn uintptr)

View File

@ -0,0 +1,11 @@
// 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.
#include "textflag.h"
#include "funcdata.h"
TEXT ·CallFn(SB),$0-4
MOVW fn+0(FP), R0
BL (R0)
RET