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