github.com/graybobo/golang.org-package-offline-cache@v0.0.0-20200626051047-6608995c132f/x/mobile/cmd/gomobile/main.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  package main
     6  
     7  //go:generate gomobile help documentation doc.go
     8  
     9  import (
    10  	"bufio"
    11  	"bytes"
    12  	"errors"
    13  	"flag"
    14  	"fmt"
    15  	"html/template"
    16  	"io"
    17  	"io/ioutil"
    18  	"log"
    19  	"os"
    20  	"os/exec"
    21  	"unicode"
    22  	"unicode/utf8"
    23  )
    24  
    25  var (
    26  	gomobileName = "gomobile"
    27  	goVersionOut = []byte(nil)
    28  	goVersion    = go1_5
    29  )
    30  
    31  func printUsage(w io.Writer) {
    32  	bufw := bufio.NewWriter(w)
    33  	if err := usageTmpl.Execute(bufw, commands); err != nil {
    34  		panic(err)
    35  	}
    36  	bufw.Flush()
    37  }
    38  
    39  func main() {
    40  	gomobileName = os.Args[0]
    41  	flag.Usage = func() {
    42  		printUsage(os.Stderr)
    43  		os.Exit(2)
    44  	}
    45  	flag.Parse()
    46  	log.SetFlags(0)
    47  
    48  	args := flag.Args()
    49  	if len(args) < 1 {
    50  		flag.Usage()
    51  	}
    52  
    53  	if args[0] == "help" {
    54  		if len(args) == 3 && args[1] == "documentation" {
    55  			helpDocumentation(args[2])
    56  			return
    57  		}
    58  		help(args[1:])
    59  		return
    60  	}
    61  
    62  	if err := determineGoVersion(); err != nil {
    63  		fmt.Fprintf(os.Stderr, "%s: %v\n", gomobileName, err)
    64  		os.Exit(1)
    65  	}
    66  
    67  	for _, cmd := range commands {
    68  		if cmd.Name == args[0] {
    69  			cmd.flag.Usage = func() {
    70  				cmd.usage()
    71  				os.Exit(1)
    72  			}
    73  			cmd.flag.Parse(args[1:])
    74  			if err := cmd.run(cmd); err != nil {
    75  				msg := err.Error()
    76  				if msg != "" {
    77  					fmt.Fprintf(os.Stderr, "%s: %v\n", os.Args[0], err)
    78  				}
    79  				os.Exit(1)
    80  			}
    81  			return
    82  		}
    83  	}
    84  	fmt.Fprintf(os.Stderr, "%s: unknown subcommand %q\nRun 'gomobile help' for usage.\n", os.Args[0], args[0])
    85  	os.Exit(2)
    86  }
    87  
    88  type goToolVersion int
    89  
    90  const (
    91  	go1_5 goToolVersion = iota
    92  	go1_6
    93  )
    94  
    95  func determineGoVersion() error {
    96  	gobin, err := exec.LookPath("go")
    97  	if err != nil {
    98  		return errors.New("go not found")
    99  	}
   100  	goVersionOut, err = exec.Command(gobin, "version").CombinedOutput()
   101  	if err != nil {
   102  		return fmt.Errorf("'go version' failed: %v, %s", err, goVersionOut)
   103  	}
   104  	switch {
   105  	case bytes.HasPrefix(goVersionOut, []byte("go version go1.4")):
   106  		return errors.New("Go 1.5 or newer is required")
   107  	case bytes.HasPrefix(goVersionOut, []byte("go version go1.5")):
   108  		goVersion = go1_5
   109  	default:
   110  		goVersion = go1_6 // assume developers are working at tip
   111  	}
   112  	return nil
   113  }
   114  
   115  func help(args []string) {
   116  	if len(args) == 0 {
   117  		printUsage(os.Stdout)
   118  		return // succeeded at helping
   119  	}
   120  	if len(args) != 1 {
   121  		fmt.Fprintf(os.Stderr, "usage: %s help command\n\nToo many arguments given.\n", gomobileName)
   122  		os.Exit(2) // failed to help
   123  	}
   124  
   125  	arg := args[0]
   126  	for _, cmd := range commands {
   127  		if cmd.Name == arg {
   128  			cmd.usage()
   129  			return // succeeded at helping
   130  		}
   131  	}
   132  
   133  	fmt.Fprintf(os.Stderr, "Unknown help topic %#q.  Run '%s help'.\n", arg, gomobileName)
   134  	os.Exit(2)
   135  }
   136  
   137  const documentationHeader = `// Copyright 2015 The Go Authors.  All rights reserved.
   138  // Use of this source code is governed by a BSD-style
   139  // license that can be found in the LICENSE file.
   140  
   141  // DO NOT EDIT. GENERATED BY 'gomobile help documentation doc.go'.
   142  `
   143  
   144  func helpDocumentation(path string) {
   145  	w := new(bytes.Buffer)
   146  	w.WriteString(documentationHeader)
   147  	w.WriteString("\n/*\n")
   148  	if err := usageTmpl.Execute(w, commands); err != nil {
   149  		log.Fatal(err)
   150  	}
   151  
   152  	for _, cmd := range commands {
   153  		r, rlen := utf8.DecodeRuneInString(cmd.Short)
   154  		w.WriteString("\n\n")
   155  		w.WriteRune(unicode.ToUpper(r))
   156  		w.WriteString(cmd.Short[rlen:])
   157  		w.WriteString("\n\nUsage:\n\n\tgomobile " + cmd.Name)
   158  		if cmd.Usage != "" {
   159  			w.WriteRune(' ')
   160  			w.WriteString(cmd.Usage)
   161  		}
   162  		w.WriteRune('\n')
   163  		w.WriteString(cmd.Long)
   164  	}
   165  
   166  	w.WriteString("*/\npackage main // import \"golang.org/x/mobile/cmd/gomobile\"\n")
   167  
   168  	if err := ioutil.WriteFile(path, w.Bytes(), 0666); err != nil {
   169  		log.Fatal(err)
   170  	}
   171  }
   172  
   173  var commands = []*command{
   174  	// TODO(crawshaw): cmdRun
   175  	cmdBind,
   176  	cmdBuild,
   177  	cmdInit,
   178  	cmdInstall,
   179  	cmdVersion,
   180  }
   181  
   182  type command struct {
   183  	run   func(*command) error
   184  	flag  flag.FlagSet
   185  	Name  string
   186  	Usage string
   187  	Short string
   188  	Long  string
   189  }
   190  
   191  func (cmd *command) usage() {
   192  	fmt.Fprintf(os.Stdout, "usage: %s %s %s\n%s", gomobileName, cmd.Name, cmd.Usage, cmd.Long)
   193  }
   194  
   195  var usageTmpl = template.Must(template.New("usage").Parse(
   196  	`Gomobile is a tool for building and running mobile apps written in Go.
   197  
   198  To install:
   199  
   200  	$ go get golang.org/x/mobile/cmd/gomobile
   201  	$ gomobile init
   202  
   203  At least Go 1.5 is required.
   204  For detailed instructions, see https://golang.org/wiki/Mobile.
   205  
   206  Usage:
   207  
   208  	gomobile command [arguments]
   209  
   210  Commands:
   211  {{range .}}
   212  	{{.Name | printf "%-11s"}} {{.Short}}{{end}}
   213  
   214  Use 'gomobile help [command]' for more information about that command.
   215  `))