Source file src/pkg/cmd/go/internal/work/build.go
1
2
3
4
5 package work
6
7 import (
8 "errors"
9 "fmt"
10 "go/build"
11 "os"
12 "os/exec"
13 "path/filepath"
14 "runtime"
15 "strings"
16
17 "cmd/go/internal/base"
18 "cmd/go/internal/cfg"
19 "cmd/go/internal/load"
20 "cmd/go/internal/search"
21 )
22
23 var CmdBuild = &base.Command{
24 UsageLine: "go build [-o output] [-i] [build flags] [packages]",
25 Short: "compile packages and dependencies",
26 Long: `
27 Build compiles the packages named by the import paths,
28 along with their dependencies, but it does not install the results.
29
30 If the arguments to build are a list of .go files from a single directory,
31 build treats them as a list of source files specifying a single package.
32
33 When compiling packages, build ignores files that end in '_test.go'.
34
35 When compiling a single main package, build writes
36 the resulting executable to an output file named after
37 the first source file ('go build ed.go rx.go' writes 'ed' or 'ed.exe')
38 or the source code directory ('go build unix/sam' writes 'sam' or 'sam.exe').
39 The '.exe' suffix is added when writing a Windows executable.
40
41 When compiling multiple packages or a single non-main package,
42 build compiles the packages but discards the resulting object,
43 serving only as a check that the packages can be built.
44
45 The -o flag forces build to write the resulting executable or object
46 to the named output file or directory, instead of the default behavior described
47 in the last two paragraphs. If the named output is a directory that exists,
48 then any resulting executables will be written to that directory.
49
50 The -i flag installs the packages that are dependencies of the target.
51
52 The build flags are shared by the build, clean, get, install, list, run,
53 and test commands:
54
55 -a
56 force rebuilding of packages that are already up-to-date.
57 -n
58 print the commands but do not run them.
59 -p n
60 the number of programs, such as build commands or
61 test binaries, that can be run in parallel.
62 The default is the number of CPUs available.
63 -race
64 enable data race detection.
65 Supported only on linux/amd64, freebsd/amd64, darwin/amd64 and windows/amd64.
66 -msan
67 enable interoperation with memory sanitizer.
68 Supported only on linux/amd64, linux/arm64
69 and only with Clang/LLVM as the host C compiler.
70 -v
71 print the names of packages as they are compiled.
72 -work
73 print the name of the temporary work directory and
74 do not delete it when exiting.
75 -x
76 print the commands.
77
78 -asmflags '[pattern=]arg list'
79 arguments to pass on each go tool asm invocation.
80 -buildmode mode
81 build mode to use. See 'go help buildmode' for more.
82 -compiler name
83 name of compiler to use, as in runtime.Compiler (gccgo or gc).
84 -gccgoflags '[pattern=]arg list'
85 arguments to pass on each gccgo compiler/linker invocation.
86 -gcflags '[pattern=]arg list'
87 arguments to pass on each go tool compile invocation.
88 -installsuffix suffix
89 a suffix to use in the name of the package installation directory,
90 in order to keep output separate from default builds.
91 If using the -race flag, the install suffix is automatically set to race
92 or, if set explicitly, has _race appended to it. Likewise for the -msan
93 flag. Using a -buildmode option that requires non-default compile flags
94 has a similar effect.
95 -ldflags '[pattern=]arg list'
96 arguments to pass on each go tool link invocation.
97 -linkshared
98 link against shared libraries previously created with
99 -buildmode=shared.
100 -mod mode
101 module download mode to use: readonly or vendor.
102 See 'go help modules' for more.
103 -pkgdir dir
104 install and load all packages from dir instead of the usual locations.
105 For example, when building with a non-standard configuration,
106 use -pkgdir to keep generated packages in a separate location.
107 -tags tag,list
108 a comma-separated list of build tags to consider satisfied during the
109 build. For more information about build tags, see the description of
110 build constraints in the documentation for the go/build package.
111 (Earlier versions of Go used a space-separated list, and that form
112 is deprecated but still recognized.)
113 -trimpath
114 remove all file system paths from the resulting executable.
115 Instead of absolute file system paths, the recorded file names
116 will begin with either "go" (for the standard library),
117 or a module path@version (when using modules),
118 or a plain import path (when using GOPATH).
119 -toolexec 'cmd args'
120 a program to use to invoke toolchain programs like vet and asm.
121 For example, instead of running asm, the go command will run
122 'cmd args /path/to/asm <arguments for asm>'.
123
124 The -asmflags, -gccgoflags, -gcflags, and -ldflags flags accept a
125 space-separated list of arguments to pass to an underlying tool
126 during the build. To embed spaces in an element in the list, surround
127 it with either single or double quotes. The argument list may be
128 preceded by a package pattern and an equal sign, which restricts
129 the use of that argument list to the building of packages matching
130 that pattern (see 'go help packages' for a description of package
131 patterns). Without a pattern, the argument list applies only to the
132 packages named on the command line. The flags may be repeated
133 with different patterns in order to specify different arguments for
134 different sets of packages. If a package matches patterns given in
135 multiple flags, the latest match on the command line wins.
136 For example, 'go build -gcflags=-S fmt' prints the disassembly
137 only for package fmt, while 'go build -gcflags=all=-S fmt'
138 prints the disassembly for fmt and all its dependencies.
139
140 For more about specifying packages, see 'go help packages'.
141 For more about where packages and binaries are installed,
142 run 'go help gopath'.
143 For more about calling between Go and C/C++, run 'go help c'.
144
145 Note: Build adheres to certain conventions such as those described
146 by 'go help gopath'. Not all projects can follow these conventions,
147 however. Installations that have their own conventions or that use
148 a separate software build system may choose to use lower-level
149 invocations such as 'go tool compile' and 'go tool link' to avoid
150 some of the overheads and design decisions of the build tool.
151
152 See also: go install, go get, go clean.
153 `,
154 }
155
156 const concurrentGCBackendCompilationEnabledByDefault = true
157
158 func init() {
159
160 CmdBuild.Run = runBuild
161 CmdInstall.Run = runInstall
162
163 CmdBuild.Flag.BoolVar(&cfg.BuildI, "i", false, "")
164 CmdBuild.Flag.StringVar(&cfg.BuildO, "o", "", "output file or directory")
165
166 CmdInstall.Flag.BoolVar(&cfg.BuildI, "i", false, "")
167
168 AddBuildFlags(CmdBuild)
169 AddBuildFlags(CmdInstall)
170 }
171
172
173
174
175 var (
176 forcedAsmflags []string
177 forcedGcflags []string
178 forcedLdflags []string
179 forcedGccgoflags []string
180 )
181
182 var BuildToolchain toolchain = noToolchain{}
183 var ldBuildmode string
184
185
186
187
188 type buildCompiler struct{}
189
190 func (c buildCompiler) Set(value string) error {
191 switch value {
192 case "gc":
193 BuildToolchain = gcToolchain{}
194 case "gccgo":
195 BuildToolchain = gccgoToolchain{}
196 default:
197 return fmt.Errorf("unknown compiler %q", value)
198 }
199 cfg.BuildToolchainName = value
200 cfg.BuildToolchainCompiler = BuildToolchain.compiler
201 cfg.BuildToolchainLinker = BuildToolchain.linker
202 cfg.BuildContext.Compiler = value
203 return nil
204 }
205
206 func (c buildCompiler) String() string {
207 return cfg.BuildContext.Compiler
208 }
209
210 func init() {
211 switch build.Default.Compiler {
212 case "gc", "gccgo":
213 buildCompiler{}.Set(build.Default.Compiler)
214 }
215 }
216
217
218
219 func AddBuildFlags(cmd *base.Command) {
220 cmd.Flag.BoolVar(&cfg.BuildA, "a", false, "")
221 cmd.Flag.BoolVar(&cfg.BuildN, "n", false, "")
222 cmd.Flag.IntVar(&cfg.BuildP, "p", cfg.BuildP, "")
223 cmd.Flag.BoolVar(&cfg.BuildV, "v", false, "")
224 cmd.Flag.BoolVar(&cfg.BuildX, "x", false, "")
225
226 cmd.Flag.Var(&load.BuildAsmflags, "asmflags", "")
227 cmd.Flag.Var(buildCompiler{}, "compiler", "")
228 cmd.Flag.StringVar(&cfg.BuildBuildmode, "buildmode", "default", "")
229 cmd.Flag.Var(&load.BuildGcflags, "gcflags", "")
230 cmd.Flag.Var(&load.BuildGccgoflags, "gccgoflags", "")
231 cmd.Flag.StringVar(&cfg.BuildMod, "mod", "", "")
232 cmd.Flag.StringVar(&cfg.BuildContext.InstallSuffix, "installsuffix", "", "")
233 cmd.Flag.Var(&load.BuildLdflags, "ldflags", "")
234 cmd.Flag.BoolVar(&cfg.BuildLinkshared, "linkshared", false, "")
235 cmd.Flag.StringVar(&cfg.BuildPkgdir, "pkgdir", "", "")
236 cmd.Flag.BoolVar(&cfg.BuildRace, "race", false, "")
237 cmd.Flag.BoolVar(&cfg.BuildMSan, "msan", false, "")
238 cmd.Flag.Var((*tagsFlag)(&cfg.BuildContext.BuildTags), "tags", "")
239 cmd.Flag.Var((*base.StringsFlag)(&cfg.BuildToolexec), "toolexec", "")
240 cmd.Flag.BoolVar(&cfg.BuildTrimpath, "trimpath", false, "")
241 cmd.Flag.BoolVar(&cfg.BuildWork, "work", false, "")
242
243
244 cmd.Flag.StringVar(&cfg.DebugActiongraph, "debug-actiongraph", "", "")
245 }
246
247
248 type tagsFlag []string
249
250 func (v *tagsFlag) Set(s string) error {
251
252 if strings.Contains(s, " ") || strings.Contains(s, "'") {
253 return (*base.StringsFlag)(v).Set(s)
254 }
255
256
257 *v = []string{}
258 for _, s := range strings.Split(s, ",") {
259 if s != "" {
260 *v = append(*v, s)
261 }
262 }
263 return nil
264 }
265
266 func (v *tagsFlag) String() string {
267 return "<TagsFlag>"
268 }
269
270
271
272
273 func fileExtSplit(file string) (name, ext string) {
274 dotExt := filepath.Ext(file)
275 name = file[:len(file)-len(dotExt)]
276 if dotExt != "" {
277 ext = dotExt[1:]
278 }
279 return
280 }
281
282 func pkgsMain(pkgs []*load.Package) (res []*load.Package) {
283 for _, p := range pkgs {
284 if p.Name == "main" {
285 res = append(res, p)
286 }
287 }
288 return res
289 }
290
291 func pkgsNotMain(pkgs []*load.Package) (res []*load.Package) {
292 for _, p := range pkgs {
293 if p.Name != "main" {
294 res = append(res, p)
295 }
296 }
297 return res
298 }
299
300 func oneMainPkg(pkgs []*load.Package) []*load.Package {
301 if len(pkgs) != 1 || pkgs[0].Name != "main" {
302 base.Fatalf("-buildmode=%s requires exactly one main package", cfg.BuildBuildmode)
303 }
304 return pkgs
305 }
306
307 var pkgsFilter = func(pkgs []*load.Package) []*load.Package { return pkgs }
308
309 var runtimeVersion = runtime.Version()
310
311 func runBuild(cmd *base.Command, args []string) {
312 BuildInit()
313 var b Builder
314 b.Init()
315
316 pkgs := load.PackagesForBuild(args)
317
318 explicitO := len(cfg.BuildO) > 0
319
320 if len(pkgs) == 1 && pkgs[0].Name == "main" && cfg.BuildO == "" {
321 cfg.BuildO = load.DefaultExecName(pkgs[0].ImportPath)
322 cfg.BuildO += cfg.ExeSuffix
323 }
324
325
326 switch cfg.BuildContext.Compiler {
327 case "gccgo":
328 if load.BuildGcflags.Present() {
329 fmt.Println("go build: when using gccgo toolchain, please pass compiler flags using -gccgoflags, not -gcflags")
330 }
331 if load.BuildLdflags.Present() {
332 fmt.Println("go build: when using gccgo toolchain, please pass linker flags using -gccgoflags, not -ldflags")
333 }
334 case "gc":
335 if load.BuildGccgoflags.Present() {
336 fmt.Println("go build: when using gc toolchain, please pass compile flags using -gcflags, and linker flags using -ldflags")
337 }
338 }
339
340 depMode := ModeBuild
341 if cfg.BuildI {
342 depMode = ModeInstall
343 }
344
345 pkgs = omitTestOnly(pkgsFilter(load.Packages(args)))
346
347
348 if cfg.BuildO == os.DevNull {
349 cfg.BuildO = ""
350 }
351
352 if cfg.BuildO != "" {
353
354
355
356 if fi, err := os.Stat(cfg.BuildO); err == nil && fi.IsDir() {
357 if !explicitO {
358 base.Fatalf("go build: build output %q already exists and is a directory", cfg.BuildO)
359 }
360 a := &Action{Mode: "go build"}
361 for _, p := range pkgs {
362 if p.Name != "main" {
363 continue
364 }
365 p.Target = filepath.Join(cfg.BuildO, load.DefaultExecName(p.ImportPath))
366 p.Target += cfg.ExeSuffix
367 p.Stale = true
368 p.StaleReason = "build -o flag in use"
369 a.Deps = append(a.Deps, b.AutoAction(ModeInstall, depMode, p))
370 }
371 if len(a.Deps) == 0 {
372 base.Fatalf("go build: no main packages to build")
373 }
374 b.Do(a)
375 return
376 }
377 if len(pkgs) > 1 {
378 base.Fatalf("go build: cannot write multiple packages to non-directory %s", cfg.BuildO)
379 } else if len(pkgs) == 0 {
380 base.Fatalf("no packages to build")
381 }
382 p := pkgs[0]
383 p.Target = cfg.BuildO
384 p.Stale = true
385 p.StaleReason = "build -o flag in use"
386 a := b.AutoAction(ModeInstall, depMode, p)
387 b.Do(a)
388 return
389 }
390
391 a := &Action{Mode: "go build"}
392 for _, p := range pkgs {
393 a.Deps = append(a.Deps, b.AutoAction(ModeBuild, depMode, p))
394 }
395 if cfg.BuildBuildmode == "shared" {
396 a = b.buildmodeShared(ModeBuild, depMode, args, pkgs, a)
397 }
398 b.Do(a)
399 }
400
401 var CmdInstall = &base.Command{
402 UsageLine: "go install [-i] [build flags] [packages]",
403 Short: "compile and install packages and dependencies",
404 Long: `
405 Install compiles and installs the packages named by the import paths.
406
407 Executables are installed in the directory named by the GOBIN environment
408 variable, which defaults to $GOPATH/bin or $HOME/go/bin if the GOPATH
409 environment variable is not set. Executables in $GOROOT
410 are installed in $GOROOT/bin or $GOTOOLDIR instead of $GOBIN.
411
412 When module-aware mode is disabled, other packages are installed in the
413 directory $GOPATH/pkg/$GOOS_$GOARCH. When module-aware mode is enabled,
414 other packages are built and cached but not installed.
415
416 The -i flag installs the dependencies of the named packages as well.
417
418 For more about the build flags, see 'go help build'.
419 For more about specifying packages, see 'go help packages'.
420
421 See also: go build, go get, go clean.
422 `,
423 }
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439 func libname(args []string, pkgs []*load.Package) (string, error) {
440 var libname string
441 appendName := func(arg string) {
442 if libname == "" {
443 libname = arg
444 } else {
445 libname += "," + arg
446 }
447 }
448 var haveNonMeta bool
449 for _, arg := range args {
450 if search.IsMetaPackage(arg) {
451 appendName(arg)
452 } else {
453 haveNonMeta = true
454 }
455 }
456 if len(libname) == 0 {
457 if len(args) == 1 && strings.HasSuffix(args[0], "/...") {
458
459 arg := strings.TrimSuffix(args[0], "/...")
460 if build.IsLocalImport(arg) {
461 cwd, _ := os.Getwd()
462 bp, _ := cfg.BuildContext.ImportDir(filepath.Join(cwd, arg), build.FindOnly)
463 if bp.ImportPath != "" && bp.ImportPath != "." {
464 arg = bp.ImportPath
465 }
466 }
467 appendName(strings.ReplaceAll(arg, "/", "-"))
468 } else {
469 for _, pkg := range pkgs {
470 appendName(strings.ReplaceAll(pkg.ImportPath, "/", "-"))
471 }
472 }
473 } else if haveNonMeta {
474 return "", errors.New("mixing of meta and non-meta packages is not allowed")
475 }
476
477
478 return "lib" + libname + ".so", nil
479 }
480
481 func runInstall(cmd *base.Command, args []string) {
482 BuildInit()
483 InstallPackages(args, load.PackagesForBuild(args))
484 }
485
486
487 func omitTestOnly(pkgs []*load.Package) []*load.Package {
488 var list []*load.Package
489 for _, p := range pkgs {
490 if len(p.GoFiles)+len(p.CgoFiles) == 0 && !p.Internal.CmdlinePkgLiteral {
491
492
493
494
495
496 continue
497 }
498 list = append(list, p)
499 }
500 return list
501 }
502
503 func InstallPackages(patterns []string, pkgs []*load.Package) {
504 if cfg.GOBIN != "" && !filepath.IsAbs(cfg.GOBIN) {
505 base.Fatalf("cannot install, GOBIN must be an absolute path")
506 }
507
508 pkgs = omitTestOnly(pkgsFilter(pkgs))
509 for _, p := range pkgs {
510 if p.Target == "" {
511 switch {
512 case p.Standard && p.ImportPath == "unsafe":
513
514 case p.Name != "main" && p.Internal.Local && p.ConflictDir == "":
515
516
517
518
519 case p.Name != "main" && p.Module != nil:
520
521 case p.Internal.GobinSubdir:
522 base.Errorf("go %s: cannot install cross-compiled binaries when GOBIN is set", cfg.CmdName)
523 case p.Internal.CmdlineFiles:
524 base.Errorf("go %s: no install location for .go files listed on command line (GOBIN not set)", cfg.CmdName)
525 case p.ConflictDir != "":
526 base.Errorf("go %s: no install location for %s: hidden by %s", cfg.CmdName, p.Dir, p.ConflictDir)
527 default:
528 base.Errorf("go %s: no install location for directory %s outside GOPATH\n"+
529 "\tFor more details see: 'go help gopath'", cfg.CmdName, p.Dir)
530 }
531 }
532 }
533 base.ExitIfErrors()
534
535 var b Builder
536 b.Init()
537 depMode := ModeBuild
538 if cfg.BuildI {
539 depMode = ModeInstall
540 }
541 a := &Action{Mode: "go install"}
542 var tools []*Action
543 for _, p := range pkgs {
544
545
546
547 a1 := b.AutoAction(ModeInstall, depMode, p)
548 if load.InstallTargetDir(p) == load.ToTool {
549 a.Deps = append(a.Deps, a1.Deps...)
550 a1.Deps = append(a1.Deps, a)
551 tools = append(tools, a1)
552 continue
553 }
554 a.Deps = append(a.Deps, a1)
555 }
556 if len(tools) > 0 {
557 a = &Action{
558 Mode: "go install (tools)",
559 Deps: tools,
560 }
561 }
562
563 if cfg.BuildBuildmode == "shared" {
564
565
566
567
568
569 a = b.buildmodeShared(ModeInstall, ModeInstall, patterns, pkgs, a)
570 }
571
572 b.Do(a)
573 base.ExitIfErrors()
574
575
576
577
578
579
580
581
582
583
584 if len(patterns) == 0 && len(pkgs) == 1 && pkgs[0].Name == "main" {
585
586
587 targ := load.DefaultExecName(pkgs[0].ImportPath)
588 targ += cfg.ExeSuffix
589 if filepath.Join(pkgs[0].Dir, targ) != pkgs[0].Target {
590 fi, err := os.Stat(targ)
591 if err == nil {
592 m := fi.Mode()
593 if m.IsRegular() {
594 if m&0111 != 0 || cfg.Goos == "windows" {
595 os.Remove(targ)
596 }
597 }
598 }
599 }
600 }
601 }
602
603
604
605
606
607
608
609 var ExecCmd []string
610
611
612
613 func FindExecCmd() []string {
614 if ExecCmd != nil {
615 return ExecCmd
616 }
617 ExecCmd = []string{}
618 if cfg.Goos == runtime.GOOS && cfg.Goarch == runtime.GOARCH {
619 return ExecCmd
620 }
621 path, err := exec.LookPath(fmt.Sprintf("go_%s_%s_exec", cfg.Goos, cfg.Goarch))
622 if err == nil {
623 ExecCmd = []string{path}
624 }
625 return ExecCmd
626 }
627
View as plain text