github.com/mdempsky/go@v0.0.0-20151201204031-5dd372bd1e70/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 for _, err := range p.DepsErrors { 93 errorf("%s", err) 94 } 95 exitIfErrors() 96 if p.Name != "main" { 97 fatalf("go run: cannot run non-main package") 98 } 99 p.target = "" // must build - not up to date 100 var src string 101 if len(p.GoFiles) > 0 { 102 src = p.GoFiles[0] 103 } else if len(p.CgoFiles) > 0 { 104 src = p.CgoFiles[0] 105 } else { 106 // this case could only happen if the provided source uses cgo 107 // while cgo is disabled. 108 hint := "" 109 if !buildContext.CgoEnabled { 110 hint = " (cgo is disabled)" 111 } 112 fatalf("go run: no suitable source files%s", hint) 113 } 114 p.exeName = src[:len(src)-len(".go")] // name temporary executable for first go file 115 a1 := b.action(modeBuild, modeBuild, p) 116 a := &action{f: (*builder).runProgram, args: cmdArgs, deps: []*action{a1}} 117 b.do(a) 118 } 119 120 // runProgram is the action for running a binary that has already 121 // been compiled. We ignore exit status. 122 func (b *builder) runProgram(a *action) error { 123 cmdline := stringList(findExecCmd(), a.deps[0].target, a.args) 124 if buildN || buildX { 125 b.showcmd("", "%s", strings.Join(cmdline, " ")) 126 if buildN { 127 return nil 128 } 129 } 130 131 runStdin(cmdline) 132 return nil 133 } 134 135 // runStdin is like run, but connects Stdin. 136 func runStdin(cmdline []string) { 137 cmd := exec.Command(cmdline[0], cmdline[1:]...) 138 cmd.Stdin = os.Stdin 139 cmd.Stdout = os.Stdout 140 cmd.Stderr = os.Stderr 141 cmd.Env = origEnv 142 startSigHandlers() 143 if err := cmd.Run(); err != nil { 144 errorf("%v", err) 145 } 146 }