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