// 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 // Gendex generates a dex file used by Go apps created with gomobile. // // The dex is a thin extension of NativeActivity, providing access to // a few platform features (not the SDK UI) not easily accessible from // NDK headers. Long term these could be made part of the standard NDK, // however that would limit gomobile to working with newer versions of // the Android OS, so we do this while we wait. // // Requires ANDROID_HOME be set to the path of the Android SDK, and // javac must be on the PATH. package main import ( "bytes" "encoding/base64" "errors" "flag" "fmt" "go/format" "io/ioutil" "log" "os" "os/exec" "path/filepath" ) var outfile = flag.String("o", "", "result will be written file") var tmpdir string func main() { flag.Parse() var err error tmpdir, err = ioutil.TempDir("", "gendex-") if err != nil { log.Fatal(err) } err = gendex() os.RemoveAll(tmpdir) if err != nil { log.Fatal(err) } } func gendex() error { androidHome := os.Getenv("ANDROID_HOME") if androidHome == "" { return errors.New("ANDROID_HOME not set") } if err := os.MkdirAll(tmpdir+"/work/org/golang/app", 0775); err != nil { return err } javaFiles, err := filepath.Glob("../../app/*.java") if err != nil { return err } if len(javaFiles) == 0 { return errors.New("could not find ../../app/*.java files") } platform, err := findLast(androidHome + "/platforms") if err != nil { return err } cmd := exec.Command( "javac", "-source", "1.7", "-target", "1.7", "-bootclasspath", platform+"/android.jar", "-d", tmpdir+"/work", ) cmd.Args = append(cmd.Args, javaFiles...) if out, err := cmd.CombinedOutput(); err != nil { fmt.Println(cmd.Args) os.Stderr.Write(out) return err } buildTools, err := findLast(androidHome + "/build-tools") if err != nil { return err } cmd = exec.Command( buildTools+"/dx", "--dex", "--output="+tmpdir+"/classes.dex", tmpdir+"/work", ) if out, err := cmd.CombinedOutput(); err != nil { os.Stderr.Write(out) return err } src, err := ioutil.ReadFile(tmpdir + "/classes.dex") if err != nil { return err } data := base64.StdEncoding.EncodeToString(src) buf := new(bytes.Buffer) fmt.Fprint(buf, header) var piece string for len(data) > 0 { l := 70 if l > len(data) { l = len(data) } piece, data = data[:l], data[l:] fmt.Fprintf(buf, "\t`%s` + \n", piece) } fmt.Fprintf(buf, "\t``") out, err := format.Source(buf.Bytes()) if err != nil { buf.WriteTo(os.Stderr) return err } w, err := os.Create(*outfile) if err != nil { return err } if _, err := w.Write(out); err != nil { return err } if err := w.Close(); err != nil { return err } return nil } func findLast(path string) (string, error) { dir, err := os.Open(path) if err != nil { return "", err } children, err := dir.Readdirnames(-1) if err != nil { return "", err } return path + "/" + children[len(children)-1], nil } var header = `// 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. // Code generated by gendex.go. DO NOT EDIT. package main var dexStr = `