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