github.com/epfl-dcsl/gotee@v0.0.0-20200909122901-014b35f5e5e9/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.BuildInit() 56 var b work.Builder 57 b.Init() 58 b.Print = printStderr 59 i := 0 60 for i < len(args) && strings.HasSuffix(args[i], ".go") { 61 i++ 62 } 63 files, cmdArgs := args[:i], args[i:] 64 if len(files) == 0 { 65 base.Fatalf("go run: no go files listed") 66 } 67 for _, file := range files { 68 if strings.HasSuffix(file, "_test.go") { 69 // GoFilesPackage is going to assign this to TestGoFiles. 70 // Reject since it won't be part of the build. 71 base.Fatalf("go run: cannot run *_test.go files (%s)", file) 72 } 73 } 74 p := load.GoFilesPackage(files) 75 if p.Error != nil { 76 base.Fatalf("%s", p.Error) 77 } 78 p.Internal.OmitDebug = true 79 if len(p.DepsErrors) > 0 { 80 // Since these are errors in dependencies, 81 // the same error might show up multiple times, 82 // once in each package that depends on it. 83 // Only print each once. 84 printed := map[*load.PackageError]bool{} 85 for _, err := range p.DepsErrors { 86 if !printed[err] { 87 printed[err] = true 88 base.Errorf("%s", err) 89 } 90 } 91 } 92 base.ExitIfErrors() 93 if p.Name != "main" { 94 base.Fatalf("go run: cannot run non-main package") 95 } 96 p.Target = "" // must build - not up to date 97 var src string 98 if len(p.GoFiles) > 0 { 99 src = p.GoFiles[0] 100 } else if len(p.CgoFiles) > 0 { 101 src = p.CgoFiles[0] 102 } else { 103 // this case could only happen if the provided source uses cgo 104 // while cgo is disabled. 105 hint := "" 106 if !cfg.BuildContext.CgoEnabled { 107 hint = " (cgo is disabled)" 108 } 109 base.Fatalf("go run: no suitable source files%s", hint) 110 } 111 p.Internal.ExeName = src[:len(src)-len(".go")] // name temporary executable for first go file 112 a1 := b.LinkAction(work.ModeBuild, work.ModeBuild, p) 113 a := &work.Action{Mode: "go run", Func: buildRunProgram, Args: cmdArgs, Deps: []*work.Action{a1}} 114 b.Do(a) 115 } 116 117 // buildRunProgram is the action for running a binary that has already 118 // been compiled. We ignore exit status. 119 func buildRunProgram(b *work.Builder, a *work.Action) error { 120 cmdline := str.StringList(work.FindExecCmd(), a.Deps[0].Target, a.Args) 121 if cfg.BuildN || cfg.BuildX { 122 b.Showcmd("", "%s", strings.Join(cmdline, " ")) 123 if cfg.BuildN { 124 return nil 125 } 126 } 127 128 base.RunStdin(cmdline) 129 return nil 130 }