github.com/tidwall/go@v0.0.0-20170415222209-6694a6888b7d/src/cmd/go/internal/run/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 run implements the ``go run'' command. 6 package run 7 8 import ( 9 "fmt" 10 "os" 11 "strings" 12 13 "cmd/go/internal/base" 14 "cmd/go/internal/cfg" 15 "cmd/go/internal/load" 16 "cmd/go/internal/str" 17 "cmd/go/internal/work" 18 ) 19 20 var CmdRun = &base.Command{ 21 UsageLine: "run [build flags] [-exec xprog] gofiles... [arguments...]", 22 Short: "compile and run Go program", 23 Long: ` 24 Run compiles and runs the main package comprising the named Go source files. 25 A Go source file is defined to be a file ending in a literal ".go" suffix. 26 27 By default, 'go run' runs the compiled binary directly: 'a.out arguments...'. 28 If the -exec flag is given, 'go run' invokes the binary using xprog: 29 'xprog a.out arguments...'. 30 If the -exec flag is not given, GOOS or GOARCH is different from the system 31 default, and a program named go_$GOOS_$GOARCH_exec can be found 32 on the current search path, 'go run' invokes the binary using that program, 33 for example 'go_nacl_386_exec a.out arguments...'. This allows execution of 34 cross-compiled programs when a simulator or other execution method is 35 available. 36 37 For more about build flags, see 'go help build'. 38 39 See also: go build. 40 `, 41 } 42 43 func init() { 44 CmdRun.Run = runRun // break init loop 45 46 work.AddBuildFlags(CmdRun) 47 CmdRun.Flag.Var((*base.StringsFlag)(&work.ExecCmd), "exec", "") 48 } 49 50 func printStderr(args ...interface{}) (int, error) { 51 return fmt.Fprint(os.Stderr, args...) 52 } 53 54 func runRun(cmd *base.Command, args []string) { 55 work.InstrumentInit() 56 work.BuildModeInit() 57 var b work.Builder 58 b.Init() 59 b.Print = printStderr 60 i := 0 61 for i < len(args) && strings.HasSuffix(args[i], ".go") { 62 i++ 63 } 64 files, cmdArgs := args[:i], args[i:] 65 if len(files) == 0 { 66 base.Fatalf("go run: no go files listed") 67 } 68 for _, file := range files { 69 if strings.HasSuffix(file, "_test.go") { 70 // GoFilesPackage is going to assign this to TestGoFiles. 71 // Reject since it won't be part of the build. 72 base.Fatalf("go run: cannot run *_test.go files (%s)", file) 73 } 74 } 75 p := load.GoFilesPackage(files) 76 if p.Error != nil { 77 base.Fatalf("%s", p.Error) 78 } 79 p.Internal.OmitDebug = true 80 if len(p.DepsErrors) > 0 { 81 // Since these are errors in dependencies, 82 // the same error might show up multiple times, 83 // once in each package that depends on it. 84 // Only print each once. 85 printed := map[*load.PackageError]bool{} 86 for _, err := range p.DepsErrors { 87 if !printed[err] { 88 printed[err] = true 89 base.Errorf("%s", err) 90 } 91 } 92 } 93 base.ExitIfErrors() 94 if p.Name != "main" { 95 base.Fatalf("go run: cannot run non-main package") 96 } 97 p.Internal.Target = "" // must build - not up to date 98 var src string 99 if len(p.GoFiles) > 0 { 100 src = p.GoFiles[0] 101 } else if len(p.CgoFiles) > 0 { 102 src = p.CgoFiles[0] 103 } else { 104 // this case could only happen if the provided source uses cgo 105 // while cgo is disabled. 106 hint := "" 107 if !cfg.BuildContext.CgoEnabled { 108 hint = " (cgo is disabled)" 109 } 110 base.Fatalf("go run: no suitable source files%s", hint) 111 } 112 p.Internal.ExeName = src[:len(src)-len(".go")] // name temporary executable for first go file 113 a1 := b.Action(work.ModeBuild, work.ModeBuild, p) 114 a := &work.Action{Func: buildRunProgram, Args: cmdArgs, Deps: []*work.Action{a1}} 115 b.Do(a) 116 } 117 118 // buildRunProgram is the action for running a binary that has already 119 // been compiled. We ignore exit status. 120 func buildRunProgram(b *work.Builder, a *work.Action) error { 121 cmdline := str.StringList(work.FindExecCmd(), a.Deps[0].Target, a.Args) 122 if cfg.BuildN || cfg.BuildX { 123 b.Showcmd("", "%s", strings.Join(cmdline, " ")) 124 if cfg.BuildN { 125 return nil 126 } 127 } 128 129 base.RunStdin(cmdline) 130 return nil 131 }