github.com/FenixAra/go@v0.0.0-20170127160404-96ea0918e670/src/cmd/go/run.go (about) 1 // Copyright 2011 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 import ( 8 "fmt" 9 "os" 10 "os/exec" 11 "runtime" 12 "strings" 13 ) 14 15 var execCmd []string // -exec flag, for run and test 16 17 func findExecCmd() []string { 18 if execCmd != nil { 19 return execCmd 20 } 21 execCmd = []string{} // avoid work the second time 22 if goos == runtime.GOOS && goarch == runtime.GOARCH { 23 return execCmd 24 } 25 path, err := exec.LookPath(fmt.Sprintf("go_%s_%s_exec", goos, goarch)) 26 if err == nil { 27 execCmd = []string{path} 28 } 29 return execCmd 30 } 31 32 var cmdRun = &Command{ 33 UsageLine: "run [build flags] [-exec xprog] gofiles... [arguments...]", 34 Short: "compile and run Go program", 35 Long: ` 36 Run compiles and runs the main package comprising the named Go source files. 37 A Go source file is defined to be a file ending in a literal ".go" suffix. 38 39 By default, 'go run' runs the compiled binary directly: 'a.out arguments...'. 40 If the -exec flag is given, 'go run' invokes the binary using xprog: 41 'xprog a.out arguments...'. 42 If the -exec flag is not given, GOOS or GOARCH is different from the system 43 default, and a program named go_$GOOS_$GOARCH_exec can be found 44 on the current search path, 'go run' invokes the binary using that program, 45 for example 'go_nacl_386_exec a.out arguments...'. This allows execution of 46 cross-compiled programs when a simulator or other execution method is 47 available. 48 49 For more about build flags, see 'go help build'. 50 51 See also: go build. 52 `, 53 } 54 55 func init() { 56 cmdRun.Run = runRun // break init loop 57 58 addBuildFlags(cmdRun) 59 cmdRun.Flag.Var((*stringsFlag)(&execCmd), "exec", "") 60 } 61 62 func printStderr(args ...interface{}) (int, error) { 63 return fmt.Fprint(os.Stderr, args...) 64 } 65 66 func runRun(cmd *Command, args []string) { 67 instrumentInit() 68 buildModeInit() 69 var b builder 70 b.init() 71 b.print = printStderr 72 i := 0 73 for i < len(args) && strings.HasSuffix(args[i], ".go") { 74 i++ 75 } 76 files, cmdArgs := args[:i], args[i:] 77 if len(files) == 0 { 78 fatalf("go run: no go files listed") 79 } 80 for _, file := range files { 81 if strings.HasSuffix(file, "_test.go") { 82 // goFilesPackage is going to assign this to TestGoFiles. 83 // Reject since it won't be part of the build. 84 fatalf("go run: cannot run *_test.go files (%s)", file) 85 } 86 } 87 p := goFilesPackage(files) 88 if p.Error != nil { 89 fatalf("%s", p.Error) 90 } 91 p.omitDWARF = true 92 if len(p.DepsErrors) > 0 { 93 // Since these are errors in dependencies, 94 // the same error might show up multiple times, 95 // once in each package that depends on it. 96 // Only print each once. 97 printed := map[*PackageError]bool{} 98 for _, err := range p.DepsErrors { 99 if !printed[err] { 100 printed[err] = true 101 errorf("%s", err) 102 } 103 } 104 } 105 exitIfErrors() 106 if p.Name != "main" { 107 fatalf("go run: cannot run non-main package") 108 } 109 p.target = "" // must build - not up to date 110 var src string 111 if len(p.GoFiles) > 0 { 112 src = p.GoFiles[0] 113 } else if len(p.CgoFiles) > 0 { 114 src = p.CgoFiles[0] 115 } else { 116 // this case could only happen if the provided source uses cgo 117 // while cgo is disabled. 118 hint := "" 119 if !buildContext.CgoEnabled { 120 hint = " (cgo is disabled)" 121 } 122 fatalf("go run: no suitable source files%s", hint) 123 } 124 p.exeName = src[:len(src)-len(".go")] // name temporary executable for first go file 125 a1 := b.action(modeBuild, modeBuild, p) 126 a := &action{f: (*builder).runProgram, args: cmdArgs, deps: []*action{a1}} 127 b.do(a) 128 } 129 130 // runProgram is the action for running a binary that has already 131 // been compiled. We ignore exit status. 132 func (b *builder) runProgram(a *action) error { 133 cmdline := stringList(findExecCmd(), a.deps[0].target, a.args) 134 if buildN || buildX { 135 b.showcmd("", "%s", strings.Join(cmdline, " ")) 136 if buildN { 137 return nil 138 } 139 } 140 141 runStdin(cmdline) 142 return nil 143 } 144 145 // runStdin is like run, but connects Stdin. 146 func runStdin(cmdline []string) { 147 cmd := exec.Command(cmdline[0], cmdline[1:]...) 148 cmd.Stdin = os.Stdin 149 cmd.Stdout = os.Stdout 150 cmd.Stderr = os.Stderr 151 cmd.Env = origEnv 152 startSigHandlers() 153 if err := cmd.Run(); err != nil { 154 errorf("%v", err) 155 } 156 }