1
2
3
4
5
6 package run
7
8 import (
9 "context"
10 "go/build"
11 "path/filepath"
12 "strings"
13
14 "cmd/go/internal/base"
15 "cmd/go/internal/cfg"
16 "cmd/go/internal/load"
17 "cmd/go/internal/modload"
18 "cmd/go/internal/str"
19 "cmd/go/internal/work"
20 )
21
22 var CmdRun = &base.Command{
23 UsageLine: "go run [build flags] [-exec xprog] package [arguments...]",
24 Short: "compile and run Go program",
25 Long: `
26 Run compiles and runs the named main Go package.
27 Typically the package is specified as a list of .go source files from a single
28 directory, but it may also be an import path, file system path, or pattern
29 matching a single known package, as in 'go run .' or 'go run my/cmd'.
30
31 If the package argument has a version suffix (like @latest or @v1.0.0),
32 "go run" builds the program in module-aware mode, ignoring the go.mod file in
33 the current directory or any parent directory, if there is one. This is useful
34 for running programs without affecting the dependencies of the main module.
35
36 If the package argument doesn't have a version suffix, "go run" may run in
37 module-aware mode or GOPATH mode, depending on the GO111MODULE environment
38 variable and the presence of a go.mod file. See 'go help modules' for details.
39 If module-aware mode is enabled, "go run" runs in the context of the main
40 module.
41
42 By default, 'go run' runs the compiled binary directly: 'a.out arguments...'.
43 If the -exec flag is given, 'go run' invokes the binary using xprog:
44 'xprog a.out arguments...'.
45 If the -exec flag is not given, GOOS or GOARCH is different from the system
46 default, and a program named go_$GOOS_$GOARCH_exec can be found
47 on the current search path, 'go run' invokes the binary using that program,
48 for example 'go_js_wasm_exec a.out arguments...'. This allows execution of
49 cross-compiled programs when a simulator or other execution method is
50 available.
51
52 By default, 'go run' compiles the binary without generating the information
53 used by debuggers, to reduce build time. To include debugger information in
54 the binary, use 'go build'.
55
56 The exit status of Run is not the exit status of the compiled binary.
57
58 For more about build flags, see 'go help build'.
59 For more about specifying packages, see 'go help packages'.
60
61 See also: go build.
62 `,
63 }
64
65 func init() {
66 CmdRun.Run = runRun
67
68 work.AddBuildFlags(CmdRun, work.DefaultBuildFlags)
69 work.AddCoverFlags(CmdRun, nil)
70 CmdRun.Flag.Var((*base.StringsFlag)(&work.ExecCmd), "exec", "")
71 }
72
73 func runRun(ctx context.Context, cmd *base.Command, args []string) {
74 moduleLoaderState := modload.NewState()
75 if shouldUseOutsideModuleMode(args) {
76
77
78
79
80 moduleLoaderState.ForceUseModules = true
81 moduleLoaderState.RootMode = modload.NoRoot
82 modload.AllowMissingModuleImports(moduleLoaderState)
83 modload.Init(moduleLoaderState)
84 } else {
85 modload.InitWorkfile(moduleLoaderState)
86 }
87
88 work.BuildInit(moduleLoaderState)
89 b := work.NewBuilder("", moduleLoaderState.VendorDirOrEmpty)
90 defer func() {
91 if err := b.Close(); err != nil {
92 base.Fatal(err)
93 }
94 }()
95
96 i := 0
97 for i < len(args) && strings.HasSuffix(args[i], ".go") {
98 i++
99 }
100 pkgOpts := load.PackageOpts{MainOnly: true}
101 var p *load.Package
102 if i > 0 {
103 files := args[:i]
104 for _, file := range files {
105 if strings.HasSuffix(file, "_test.go") {
106
107
108 base.Fatalf("go: cannot run *_test.go files (%s)", file)
109 }
110 }
111 p = load.GoFilesPackage(moduleLoaderState, ctx, pkgOpts, files)
112 } else if len(args) > 0 && !strings.HasPrefix(args[0], "-") {
113 arg := args[0]
114 var pkgs []*load.Package
115 if strings.Contains(arg, "@") && !build.IsLocalImport(arg) && !filepath.IsAbs(arg) {
116 var err error
117 pkgs, err = load.PackagesAndErrorsOutsideModule(moduleLoaderState, ctx, pkgOpts, args[:1])
118 if err != nil {
119 base.Fatal(err)
120 }
121 } else {
122 pkgs = load.PackagesAndErrors(moduleLoaderState, ctx, pkgOpts, args[:1])
123 }
124
125 if len(pkgs) == 0 {
126 base.Fatalf("go: no packages loaded from %s", arg)
127 }
128 if len(pkgs) > 1 {
129 names := make([]string, 0, len(pkgs))
130 for _, p := range pkgs {
131 names = append(names, p.ImportPath)
132 }
133 base.Fatalf("go: pattern %s matches multiple packages:\n\t%s", arg, strings.Join(names, "\n\t"))
134 }
135 p = pkgs[0]
136 i++
137 } else {
138 base.Fatalf("go: no go files listed")
139 }
140 cmdArgs := args[i:]
141 load.CheckPackageErrors([]*load.Package{p})
142
143 if cfg.BuildCover {
144 load.PrepareForCoverageBuild(moduleLoaderState, []*load.Package{p})
145 }
146
147 p.Internal.OmitDebug = true
148 p.Target = ""
149 if p.Internal.CmdlineFiles {
150
151 var src string
152 if len(p.GoFiles) > 0 {
153 src = p.GoFiles[0]
154 } else if len(p.CgoFiles) > 0 {
155 src = p.CgoFiles[0]
156 } else {
157
158
159 hint := ""
160 if !cfg.BuildContext.CgoEnabled {
161 hint = " (cgo is disabled)"
162 }
163 base.Fatalf("go: no suitable source files%s", hint)
164 }
165 p.Internal.ExeName = src[:len(src)-len(".go")]
166 } else {
167 p.Internal.ExeName = p.DefaultExecName()
168 }
169
170 a1 := b.LinkAction(moduleLoaderState, work.ModeBuild, work.ModeBuild, p)
171 a1.CacheExecutable = true
172 a := &work.Action{Mode: "go run", Actor: work.ActorFunc(buildRunProgram), Args: cmdArgs, Deps: []*work.Action{a1}}
173 b.Do(ctx, a)
174 }
175
176
177
178
179
180
181
182
183
184
185
186
187 func shouldUseOutsideModuleMode(args []string) bool {
188
189
190 return len(args) > 0 &&
191 !strings.HasSuffix(args[0], ".go") &&
192 !strings.HasPrefix(args[0], "-") &&
193 strings.Contains(args[0], "@") &&
194 !build.IsLocalImport(args[0]) &&
195 !filepath.IsAbs(args[0])
196 }
197
198
199
200 func buildRunProgram(b *work.Builder, ctx context.Context, a *work.Action) error {
201 cmdline := str.StringList(work.FindExecCmd(), a.Deps[0].BuiltTarget(), a.Args)
202 if cfg.BuildN || cfg.BuildX {
203 b.Shell(a).ShowCmd("", "%s", strings.Join(cmdline, " "))
204 if cfg.BuildN {
205 return nil
206 }
207 }
208
209 base.RunStdin(cmdline)
210 return nil
211 }
212
View as plain text