github.com/acrespo/mobile@v0.0.0-20190107162257-dc0771356504/cmd/gomobile/gendex.go (about) 1 // Copyright 2015 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 // +build ignore 6 7 // Gendex generates a dex file used by Go apps created with gomobile. 8 // 9 // The dex is a thin extension of NativeActivity, providing access to 10 // a few platform features (not the SDK UI) not easily accessible from 11 // NDK headers. Long term these could be made part of the standard NDK, 12 // however that would limit gomobile to working with newer versions of 13 // the Android OS, so we do this while we wait. 14 // 15 // Requires ANDROID_HOME be set to the path of the Android SDK, and 16 // javac must be on the PATH. 17 package main 18 19 import ( 20 "bytes" 21 "encoding/base64" 22 "errors" 23 "flag" 24 "fmt" 25 "go/format" 26 "io/ioutil" 27 "log" 28 "os" 29 "os/exec" 30 "path/filepath" 31 ) 32 33 var outfile = flag.String("o", "", "result will be written file") 34 35 var tmpdir string 36 37 func main() { 38 flag.Parse() 39 40 var err error 41 tmpdir, err = ioutil.TempDir("", "gendex-") 42 if err != nil { 43 log.Fatal(err) 44 } 45 46 err = gendex() 47 os.RemoveAll(tmpdir) 48 if err != nil { 49 log.Fatal(err) 50 } 51 } 52 53 func gendex() error { 54 androidHome := os.Getenv("ANDROID_HOME") 55 if androidHome == "" { 56 return errors.New("ANDROID_HOME not set") 57 } 58 if err := os.MkdirAll(tmpdir+"/work/org/golang/app", 0775); err != nil { 59 return err 60 } 61 javaFiles, err := filepath.Glob("../../app/*.java") 62 if err != nil { 63 return err 64 } 65 if len(javaFiles) == 0 { 66 return errors.New("could not find ../../app/*.java files") 67 } 68 platform, err := findLast(androidHome + "/platforms") 69 if err != nil { 70 return err 71 } 72 cmd := exec.Command( 73 "javac", 74 "-source", "1.7", 75 "-target", "1.7", 76 "-bootclasspath", platform+"/android.jar", 77 "-d", tmpdir+"/work", 78 ) 79 cmd.Args = append(cmd.Args, javaFiles...) 80 if out, err := cmd.CombinedOutput(); err != nil { 81 fmt.Println(cmd.Args) 82 os.Stderr.Write(out) 83 return err 84 } 85 buildTools, err := findLast(androidHome + "/build-tools") 86 if err != nil { 87 return err 88 } 89 cmd = exec.Command( 90 buildTools+"/dx", 91 "--dex", 92 "--output="+tmpdir+"/classes.dex", 93 tmpdir+"/work", 94 ) 95 if out, err := cmd.CombinedOutput(); err != nil { 96 os.Stderr.Write(out) 97 return err 98 } 99 src, err := ioutil.ReadFile(tmpdir + "/classes.dex") 100 if err != nil { 101 return err 102 } 103 data := base64.StdEncoding.EncodeToString(src) 104 105 buf := new(bytes.Buffer) 106 fmt.Fprint(buf, header) 107 108 var piece string 109 for len(data) > 0 { 110 l := 70 111 if l > len(data) { 112 l = len(data) 113 } 114 piece, data = data[:l], data[l:] 115 fmt.Fprintf(buf, "\t`%s` + \n", piece) 116 } 117 fmt.Fprintf(buf, "\t``") 118 out, err := format.Source(buf.Bytes()) 119 if err != nil { 120 buf.WriteTo(os.Stderr) 121 return err 122 } 123 124 w, err := os.Create(*outfile) 125 if err != nil { 126 return err 127 } 128 if _, err := w.Write(out); err != nil { 129 return err 130 } 131 if err := w.Close(); err != nil { 132 return err 133 } 134 return nil 135 } 136 137 func findLast(path string) (string, error) { 138 dir, err := os.Open(path) 139 if err != nil { 140 return "", err 141 } 142 children, err := dir.Readdirnames(-1) 143 if err != nil { 144 return "", err 145 } 146 return path + "/" + children[len(children)-1], nil 147 } 148 149 var header = `// Copyright 2015 The Go Authors. All rights reserved. 150 // Use of this source code is governed by a BSD-style 151 // license that can be found in the LICENSE file. 152 153 // Code generated by gendex.go. DO NOT EDIT. 154 155 package main 156 157 var dexStr = `