github.com/SpiderOak/mobile@v0.0.0-20221129182558-6f541b59af45/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  // Respects ANDROID_HOME to set the path of the Android SDK.
    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  	"github.com/SpiderOak/mobile/internal/sdkpath"
    34  )
    35  
    36  var outfile = flag.String("o", "", "result will be written file")
    37  
    38  var tmpdir string
    39  
    40  func main() {
    41  	flag.Parse()
    42  
    43  	var err error
    44  	tmpdir, err = ioutil.TempDir("", "gendex-")
    45  	if err != nil {
    46  		log.Fatal(err)
    47  	}
    48  
    49  	err = gendex()
    50  	os.RemoveAll(tmpdir)
    51  	if err != nil {
    52  		log.Fatal(err)
    53  	}
    54  }
    55  
    56  func gendex() error {
    57  	androidHome, err := sdkpath.AndroidHome()
    58  	if err != nil {
    59  		return fmt.Errorf("couldn't find Android SDK: %w", err)
    60  	}
    61  	if err := os.MkdirAll(tmpdir+"/work/org/golang/app", 0775); err != nil {
    62  		return err
    63  	}
    64  	javaFiles, err := filepath.Glob("../../app/*.java")
    65  	if err != nil {
    66  		return err
    67  	}
    68  	if len(javaFiles) == 0 {
    69  		return errors.New("could not find ../../app/*.java files")
    70  	}
    71  	platform, err := findLast(androidHome + "/platforms")
    72  	if err != nil {
    73  		return err
    74  	}
    75  	cmd := exec.Command(
    76  		"javac",
    77  		"-source", "1.7",
    78  		"-target", "1.7",
    79  		"-bootclasspath", platform+"/android.jar",
    80  		"-d", tmpdir+"/work",
    81  	)
    82  	cmd.Args = append(cmd.Args, javaFiles...)
    83  	if out, err := cmd.CombinedOutput(); err != nil {
    84  		fmt.Println(cmd.Args)
    85  		os.Stderr.Write(out)
    86  		return err
    87  	}
    88  	buildTools, err := findLast(androidHome + "/build-tools")
    89  	if err != nil {
    90  		return err
    91  	}
    92  	cmd = exec.Command(
    93  		buildTools+"/dx",
    94  		"--dex",
    95  		"--output="+tmpdir+"/classes.dex",
    96  		tmpdir+"/work",
    97  	)
    98  	if out, err := cmd.CombinedOutput(); err != nil {
    99  		os.Stderr.Write(out)
   100  		return err
   101  	}
   102  	src, err := ioutil.ReadFile(tmpdir + "/classes.dex")
   103  	if err != nil {
   104  		return err
   105  	}
   106  	data := base64.StdEncoding.EncodeToString(src)
   107  
   108  	buf := new(bytes.Buffer)
   109  	fmt.Fprint(buf, header)
   110  
   111  	var piece string
   112  	for len(data) > 0 {
   113  		l := 70
   114  		if l > len(data) {
   115  			l = len(data)
   116  		}
   117  		piece, data = data[:l], data[l:]
   118  		fmt.Fprintf(buf, "\t`%s` + \n", piece)
   119  	}
   120  	fmt.Fprintf(buf, "\t``")
   121  	out, err := format.Source(buf.Bytes())
   122  	if err != nil {
   123  		buf.WriteTo(os.Stderr)
   124  		return err
   125  	}
   126  
   127  	w, err := os.Create(*outfile)
   128  	if err != nil {
   129  		return err
   130  	}
   131  	if _, err := w.Write(out); err != nil {
   132  		return err
   133  	}
   134  	if err := w.Close(); err != nil {
   135  		return err
   136  	}
   137  	return nil
   138  }
   139  
   140  func findLast(path string) (string, error) {
   141  	dir, err := os.Open(path)
   142  	if err != nil {
   143  		return "", err
   144  	}
   145  	children, err := dir.Readdirnames(-1)
   146  	if err != nil {
   147  		return "", err
   148  	}
   149  	return path + "/" + children[len(children)-1], nil
   150  }
   151  
   152  var header = `// Copyright 2015 The Go Authors.  All rights reserved.
   153  // Use of this source code is governed by a BSD-style
   154  // license that can be found in the LICENSE file.
   155  
   156  // Code generated by gendex.go. DO NOT EDIT.
   157  
   158  package main
   159  
   160  var dexStr = `