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