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 `))