1
2
3
4
5 package work
6
7 import (
8 "context"
9 "errors"
10 "fmt"
11 "go/build"
12 exec "internal/execabs"
13 "os"
14 "path/filepath"
15 "runtime"
16 "strings"
17
18 "cmd/go/internal/base"
19 "cmd/go/internal/cfg"
20 "cmd/go/internal/fsys"
21 "cmd/go/internal/load"
22 "cmd/go/internal/modload"
23 "cmd/go/internal/search"
24 "cmd/go/internal/trace"
25 )
26
27 var CmdBuild = &base.Command{
28 UsageLine: "go build [-o output] [build flags] [packages]",
29 Short: "compile packages and dependencies",
30 Long: `
31 Build compiles the packages named by the import paths,
32 along with their dependencies, but it does not install the results.
33
34 If the arguments to build are a list of .go files from a single directory,
35 build treats them as a list of source files specifying a single package.
36
37 When compiling packages, build ignores files that end in '_test.go'.
38
39 When compiling a single main package, build writes
40 the resulting executable to an output file named after
41 the first source file ('go build ed.go rx.go' writes 'ed' or 'ed.exe')
42 or the source code directory ('go build unix/sam' writes 'sam' or 'sam.exe').
43 The '.exe' suffix is added when writing a Windows executable.
44
45 When compiling multiple packages or a single non-main package,
46 build compiles the packages but discards the resulting object,
47 serving only as a check that the packages can be built.
48
49 The -o flag forces build to write the resulting executable or object
50 to the named output file or directory, instead of the default behavior described
51 in the last two paragraphs. If the named output is an existing directory or
52 ends with a slash or backslash, then any resulting executables
53 will be written to that directory.
54
55 The -i flag installs the packages that are dependencies of the target.
56 The -i flag is deprecated. Compiled packages are cached automatically.
57
58 The build flags are shared by the build, clean, get, install, list, run,
59 and test commands:
60
61 -a
62 force rebuilding of packages that are already up-to-date.
63 -n
64 print the commands but do not run them.
65 -p n
66 the number of programs, such as build commands or
67 test binaries, that can be run in parallel.
68 The default is GOMAXPROCS, normally the number of CPUs available.
69 -race
70 enable data race detection.
71 Supported only on linux/amd64, freebsd/amd64, darwin/amd64, windows/amd64,
72 linux/ppc64le and linux/arm64 (only for 48-bit VMA).
73 -msan
74 enable interoperation with memory sanitizer.
75 Supported only on linux/amd64, linux/arm64
76 and only with Clang/LLVM as the host C compiler.
77 On linux/arm64, pie build mode will be used.
78 -v
79 print the names of packages as they are compiled.
80 -work
81 print the name of the temporary work directory and
82 do not delete it when exiting.
83 -x
84 print the commands.
85
86 -asmflags '[pattern=]arg list'
87 arguments to pass on each go tool asm invocation.
88 -buildmode mode
89 build mode to use. See 'go help buildmode' for more.
90 -compiler name
91 name of compiler to use, as in runtime.Compiler (gccgo or gc).
92 -gccgoflags '[pattern=]arg list'
93 arguments to pass on each gccgo compiler/linker invocation.
94 -gcflags '[pattern=]arg list'
95 arguments to pass on each go tool compile invocation.
96 -installsuffix suffix
97 a suffix to use in the name of the package installation directory,
98 in order to keep output separate from default builds.
99 If using the -race flag, the install suffix is automatically set to race
100 or, if set explicitly, has _race appended to it. Likewise for the -msan
101 flag. Using a -buildmode option that requires non-default compile flags
102 has a similar effect.
103 -ldflags '[pattern=]arg list'
104 arguments to pass on each go tool link invocation.
105 -linkshared
106 build code that will be linked against shared libraries previously
107 created with -buildmode=shared.
108 -mod mode
109 module download mode to use: readonly, vendor, or mod.
110 By default, if a vendor directory is present and the go version in go.mod
111 is 1.14 or higher, the go command acts as if -mod=vendor were set.
112 Otherwise, the go command acts as if -mod=readonly were set.
113 See https://golang.org/ref/mod#build-commands for details.
114 -modcacherw
115 leave newly-created directories in the module cache read-write
116 instead of making them read-only.
117 -modfile file
118 in module aware mode, read (and possibly write) an alternate go.mod
119 file instead of the one in the module root directory. A file named
120 "go.mod" must still be present in order to determine the module root
121 directory, but it is not accessed. When -modfile is specified, an
122 alternate go.sum file is also used: its path is derived from the
123 -modfile flag by trimming the ".mod" extension and appending ".sum".
124 -overlay file
125 read a JSON config file that provides an overlay for build operations.
126 The file is a JSON struct with a single field, named 'Replace', that
127 maps each disk file path (a string) to its backing file path, so that
128 a build will run as if the disk file path exists with the contents
129 given by the backing file paths, or as if the disk file path does not
130 exist if its backing file path is empty. Support for the -overlay flag
131 has some limitations: importantly, cgo files included from outside the
132 include path must be in the same directory as the Go package they are
133 included from, and overlays will not appear when binaries and tests are
134 run through go run and go test respectively.
135 -pkgdir dir
136 install and load all packages from dir instead of the usual locations.
137 For example, when building with a non-standard configuration,
138 use -pkgdir to keep generated packages in a separate location.
139 -tags tag,list
140 a comma-separated list of build tags to consider satisfied during the
141 build. For more information about build tags, see the description of
142 build constraints in the documentation for the go/build package.
143 (Earlier versions of Go used a space-separated list, and that form
144 is deprecated but still recognized.)
145 -trimpath
146 remove all file system paths from the resulting executable.
147 Instead of absolute file system paths, the recorded file names
148 will begin with either "go" (for the standard library),
149 or a module path@version (when using modules),
150 or a plain import path (when using GOPATH).
151 -toolexec 'cmd args'
152 a program to use to invoke toolchain programs like vet and asm.
153 For example, instead of running asm, the go command will run
154 'cmd args /path/to/asm <arguments for asm>'.
155 The TOOLEXEC_IMPORTPATH environment variable will be set,
156 matching 'go list -f {{.ImportPath}}' for the package being built.
157
158 The -asmflags, -gccgoflags, -gcflags, and -ldflags flags accept a
159 space-separated list of arguments to pass to an underlying tool
160 during the build. To embed spaces in an element in the list, surround
161 it with either single or double quotes. The argument list may be
162 preceded by a package pattern and an equal sign, which restricts
163 the use of that argument list to the building of packages matching
164 that pattern (see 'go help packages' for a description of package
165 patterns). Without a pattern, the argument list applies only to the
166 packages named on the command line. The flags may be repeated
167 with different patterns in order to specify different arguments for
168 different sets of packages. If a package matches patterns given in
169 multiple flags, the latest match on the command line wins.
170 For example, 'go build -gcflags=-S fmt' prints the disassembly
171 only for package fmt, while 'go build -gcflags=all=-S fmt'
172 prints the disassembly for fmt and all its dependencies.
173
174 For more about specifying packages, see 'go help packages'.
175 For more about where packages and binaries are installed,
176 run 'go help gopath'.
177 For more about calling between Go and C/C++, run 'go help c'.
178
179 Note: Build adheres to certain conventions such as those described
180 by 'go help gopath'. Not all projects can follow these conventions,
181 however. Installations that have their own conventions or that use
182 a separate software build system may choose to use lower-level
183 invocations such as 'go tool compile' and 'go tool link' to avoid
184 some of the overheads and design decisions of the build tool.
185
186 See also: go install, go get, go clean.
187 `,
188 }
189
190 const concurrentGCBackendCompilationEnabledByDefault = true
191
192 func init() {
193
194 CmdBuild.Run = runBuild
195 CmdInstall.Run = runInstall
196
197 CmdBuild.Flag.BoolVar(&cfg.BuildI, "i", false, "")
198 CmdBuild.Flag.StringVar(&cfg.BuildO, "o", "", "output file or directory")
199
200 CmdInstall.Flag.BoolVar(&cfg.BuildI, "i", false, "")
201
202 AddBuildFlags(CmdBuild, DefaultBuildFlags)
203 AddBuildFlags(CmdInstall, DefaultBuildFlags)
204 }
205
206
207
208
209 var (
210 forcedAsmflags []string
211 forcedGcflags []string
212 forcedLdflags []string
213 forcedGccgoflags []string
214 )
215
216 var BuildToolchain toolchain = noToolchain{}
217 var ldBuildmode string
218
219
220
221
222 type buildCompiler struct{}
223
224 func (c buildCompiler) Set(value string) error {
225 switch value {
226 case "gc":
227 BuildToolchain = gcToolchain{}
228 case "gccgo":
229 BuildToolchain = gccgoToolchain{}
230 default:
231 return fmt.Errorf("unknown compiler %q", value)
232 }
233 cfg.BuildToolchainName = value
234 cfg.BuildToolchainCompiler = BuildToolchain.compiler
235 cfg.BuildToolchainLinker = BuildToolchain.linker
236 cfg.BuildContext.Compiler = value
237 return nil
238 }
239
240 func (c buildCompiler) String() string {
241 return cfg.BuildContext.Compiler
242 }
243
244 func init() {
245 switch build.Default.Compiler {
246 case "gc", "gccgo":
247 buildCompiler{}.Set(build.Default.Compiler)
248 }
249 }
250
251 type BuildFlagMask int
252
253 const (
254 DefaultBuildFlags BuildFlagMask = 0
255 OmitModFlag BuildFlagMask = 1 << iota
256 OmitModCommonFlags
257 OmitVFlag
258 )
259
260
261
262 func AddBuildFlags(cmd *base.Command, mask BuildFlagMask) {
263 base.AddBuildFlagsNX(&cmd.Flag)
264 cmd.Flag.BoolVar(&cfg.BuildA, "a", false, "")
265 cmd.Flag.IntVar(&cfg.BuildP, "p", cfg.BuildP, "")
266 if mask&OmitVFlag == 0 {
267 cmd.Flag.BoolVar(&cfg.BuildV, "v", false, "")
268 }
269
270 cmd.Flag.Var(&load.BuildAsmflags, "asmflags", "")
271 cmd.Flag.Var(buildCompiler{}, "compiler", "")
272 cmd.Flag.StringVar(&cfg.BuildBuildmode, "buildmode", "default", "")
273 cmd.Flag.Var(&load.BuildGcflags, "gcflags", "")
274 cmd.Flag.Var(&load.BuildGccgoflags, "gccgoflags", "")
275 if mask&OmitModFlag == 0 {
276 base.AddModFlag(&cmd.Flag)
277 }
278 if mask&OmitModCommonFlags == 0 {
279 base.AddModCommonFlags(&cmd.Flag)
280 } else {
281
282
283
284 cmd.Flag.StringVar(&fsys.OverlayFile, "overlay", "", "")
285 }
286 cmd.Flag.StringVar(&cfg.BuildContext.InstallSuffix, "installsuffix", "", "")
287 cmd.Flag.Var(&load.BuildLdflags, "ldflags", "")
288 cmd.Flag.BoolVar(&cfg.BuildLinkshared, "linkshared", false, "")
289 cmd.Flag.StringVar(&cfg.BuildPkgdir, "pkgdir", "", "")
290 cmd.Flag.BoolVar(&cfg.BuildRace, "race", false, "")
291 cmd.Flag.BoolVar(&cfg.BuildMSan, "msan", false, "")
292 cmd.Flag.Var((*tagsFlag)(&cfg.BuildContext.BuildTags), "tags", "")
293 cmd.Flag.Var((*base.StringsFlag)(&cfg.BuildToolexec), "toolexec", "")
294 cmd.Flag.BoolVar(&cfg.BuildTrimpath, "trimpath", false, "")
295 cmd.Flag.BoolVar(&cfg.BuildWork, "work", false, "")
296
297
298 cmd.Flag.StringVar(&cfg.DebugActiongraph, "debug-actiongraph", "", "")
299 cmd.Flag.StringVar(&cfg.DebugTrace, "debug-trace", "", "")
300 }
301
302
303 type tagsFlag []string
304
305 func (v *tagsFlag) Set(s string) error {
306
307 if strings.Contains(s, " ") || strings.Contains(s, "'") {
308 return (*base.StringsFlag)(v).Set(s)
309 }
310
311
312 *v = []string{}
313 for _, s := range strings.Split(s, ",") {
314 if s != "" {
315 *v = append(*v, s)
316 }
317 }
318 return nil
319 }
320
321 func (v *tagsFlag) String() string {
322 return "<TagsFlag>"
323 }
324
325
326
327
328 func fileExtSplit(file string) (name, ext string) {
329 dotExt := filepath.Ext(file)
330 name = file[:len(file)-len(dotExt)]
331 if dotExt != "" {
332 ext = dotExt[1:]
333 }
334 return
335 }
336
337 func pkgsMain(pkgs []*load.Package) (res []*load.Package) {
338 for _, p := range pkgs {
339 if p.Name == "main" {
340 res = append(res, p)
341 }
342 }
343 return res
344 }
345
346 func pkgsNotMain(pkgs []*load.Package) (res []*load.Package) {
347 for _, p := range pkgs {
348 if p.Name != "main" {
349 res = append(res, p)
350 }
351 }
352 return res
353 }
354
355 func oneMainPkg(pkgs []*load.Package) []*load.Package {
356 if len(pkgs) != 1 || pkgs[0].Name != "main" {
357 base.Fatalf("-buildmode=%s requires exactly one main package", cfg.BuildBuildmode)
358 }
359 return pkgs
360 }
361
362 var pkgsFilter = func(pkgs []*load.Package) []*load.Package { return pkgs }
363
364 var runtimeVersion = runtime.Version()
365
366 func runBuild(ctx context.Context, cmd *base.Command, args []string) {
367 BuildInit()
368 var b Builder
369 b.Init()
370
371 pkgs := load.PackagesAndErrors(ctx, load.PackageOpts{}, args)
372 load.CheckPackageErrors(pkgs)
373
374 explicitO := len(cfg.BuildO) > 0
375
376 if len(pkgs) == 1 && pkgs[0].Name == "main" && cfg.BuildO == "" {
377 cfg.BuildO = pkgs[0].DefaultExecName()
378 cfg.BuildO += cfg.ExeSuffix
379 }
380
381
382 switch cfg.BuildContext.Compiler {
383 case "gccgo":
384 if load.BuildGcflags.Present() {
385 fmt.Println("go build: when using gccgo toolchain, please pass compiler flags using -gccgoflags, not -gcflags")
386 }
387 if load.BuildLdflags.Present() {
388 fmt.Println("go build: when using gccgo toolchain, please pass linker flags using -gccgoflags, not -ldflags")
389 }
390 case "gc":
391 if load.BuildGccgoflags.Present() {
392 fmt.Println("go build: when using gc toolchain, please pass compile flags using -gcflags, and linker flags using -ldflags")
393 }
394 }
395
396 depMode := ModeBuild
397 if cfg.BuildI {
398 depMode = ModeInstall
399 fmt.Fprint(os.Stderr, "go build: -i flag is deprecated\n")
400 }
401
402 pkgs = omitTestOnly(pkgsFilter(pkgs))
403
404
405 if cfg.BuildO == os.DevNull {
406 cfg.BuildO = ""
407 }
408
409 if cfg.BuildO != "" {
410
411
412
413
414 if fi, err := os.Stat(cfg.BuildO); (err == nil && fi.IsDir()) ||
415 strings.HasSuffix(cfg.BuildO, "/") ||
416 strings.HasSuffix(cfg.BuildO, string(os.PathSeparator)) {
417 if !explicitO {
418 base.Fatalf("go build: build output %q already exists and is a directory", cfg.BuildO)
419 }
420 a := &Action{Mode: "go build"}
421 for _, p := range pkgs {
422 if p.Name != "main" {
423 continue
424 }
425
426 p.Target = filepath.Join(cfg.BuildO, p.DefaultExecName())
427 p.Target += cfg.ExeSuffix
428 p.Stale = true
429 p.StaleReason = "build -o flag in use"
430 a.Deps = append(a.Deps, b.AutoAction(ModeInstall, depMode, p))
431 }
432 if len(a.Deps) == 0 {
433 base.Fatalf("go build: no main packages to build")
434 }
435 b.Do(ctx, a)
436 return
437 }
438 if len(pkgs) > 1 {
439 base.Fatalf("go build: cannot write multiple packages to non-directory %s", cfg.BuildO)
440 } else if len(pkgs) == 0 {
441 base.Fatalf("no packages to build")
442 }
443 p := pkgs[0]
444 p.Target = cfg.BuildO
445 p.Stale = true
446 p.StaleReason = "build -o flag in use"
447 a := b.AutoAction(ModeInstall, depMode, p)
448 b.Do(ctx, a)
449 return
450 }
451
452 a := &Action{Mode: "go build"}
453 for _, p := range pkgs {
454 a.Deps = append(a.Deps, b.AutoAction(ModeBuild, depMode, p))
455 }
456 if cfg.BuildBuildmode == "shared" {
457 a = b.buildmodeShared(ModeBuild, depMode, args, pkgs, a)
458 }
459 b.Do(ctx, a)
460 }
461
462 var CmdInstall = &base.Command{
463 UsageLine: "go install [build flags] [packages]",
464 Short: "compile and install packages and dependencies",
465 Long: `
466 Install compiles and installs the packages named by the import paths.
467
468 Executables are installed in the directory named by the GOBIN environment
469 variable, which defaults to $GOPATH/bin or $HOME/go/bin if the GOPATH
470 environment variable is not set. Executables in $GOROOT
471 are installed in $GOROOT/bin or $GOTOOLDIR instead of $GOBIN.
472
473 If the arguments have version suffixes (like @latest or @v1.0.0), "go install"
474 builds packages in module-aware mode, ignoring the go.mod file in the current
475 directory or any parent directory, if there is one. This is useful for
476 installing executables without affecting the dependencies of the main module.
477 To eliminate ambiguity about which module versions are used in the build, the
478 arguments must satisfy the following constraints:
479
480 - Arguments must be package paths or package patterns (with "..." wildcards).
481 They must not be standard packages (like fmt), meta-patterns (std, cmd,
482 all), or relative or absolute file paths.
483
484 - All arguments must have the same version suffix. Different queries are not
485 allowed, even if they refer to the same version.
486
487 - All arguments must refer to packages in the same module at the same version.
488
489 - No module is considered the "main" module. If the module containing
490 packages named on the command line has a go.mod file, it must not contain
491 directives (replace and exclude) that would cause it to be interpreted
492 differently than if it were the main module. The module must not require
493 a higher version of itself.
494
495 - Package path arguments must refer to main packages. Pattern arguments
496 will only match main packages.
497
498 If the arguments don't have version suffixes, "go install" may run in
499 module-aware mode or GOPATH mode, depending on the GO111MODULE environment
500 variable and the presence of a go.mod file. See 'go help modules' for details.
501 If module-aware mode is enabled, "go install" runs in the context of the main
502 module.
503
504 When module-aware mode is disabled, other packages are installed in the
505 directory $GOPATH/pkg/$GOOS_$GOARCH. When module-aware mode is enabled,
506 other packages are built and cached but not installed.
507
508 The -i flag installs the dependencies of the named packages as well.
509 The -i flag is deprecated. Compiled packages are cached automatically.
510
511 For more about the build flags, see 'go help build'.
512 For more about specifying packages, see 'go help packages'.
513
514 See also: go build, go get, go clean.
515 `,
516 }
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532 func libname(args []string, pkgs []*load.Package) (string, error) {
533 var libname string
534 appendName := func(arg string) {
535 if libname == "" {
536 libname = arg
537 } else {
538 libname += "," + arg
539 }
540 }
541 var haveNonMeta bool
542 for _, arg := range args {
543 if search.IsMetaPackage(arg) {
544 appendName(arg)
545 } else {
546 haveNonMeta = true
547 }
548 }
549 if len(libname) == 0 {
550 if len(args) == 1 && strings.HasSuffix(args[0], "/...") {
551
552 arg := strings.TrimSuffix(args[0], "/...")
553 if build.IsLocalImport(arg) {
554 cwd, _ := os.Getwd()
555 bp, _ := cfg.BuildContext.ImportDir(filepath.Join(cwd, arg), build.FindOnly)
556 if bp.ImportPath != "" && bp.ImportPath != "." {
557 arg = bp.ImportPath
558 }
559 }
560 appendName(strings.ReplaceAll(arg, "/", "-"))
561 } else {
562 for _, pkg := range pkgs {
563 appendName(strings.ReplaceAll(pkg.ImportPath, "/", "-"))
564 }
565 }
566 } else if haveNonMeta {
567 return "", errors.New("mixing of meta and non-meta packages is not allowed")
568 }
569
570
571 return "lib" + libname + ".so", nil
572 }
573
574 func runInstall(ctx context.Context, cmd *base.Command, args []string) {
575
576
577
578
579
580 for _, arg := range args {
581 if strings.Contains(arg, "@") && !build.IsLocalImport(arg) && !filepath.IsAbs(arg) {
582 if cfg.BuildI {
583 fmt.Fprint(os.Stderr, "go install: -i flag is deprecated\n")
584 }
585 installOutsideModule(ctx, args)
586 return
587 }
588 }
589
590 BuildInit()
591 pkgs := load.PackagesAndErrors(ctx, load.PackageOpts{}, args)
592 if cfg.ModulesEnabled && !modload.HasModRoot() {
593 haveErrors := false
594 allMissingErrors := true
595 for _, pkg := range pkgs {
596 if pkg.Error == nil {
597 continue
598 }
599 haveErrors = true
600 if missingErr := (*modload.ImportMissingError)(nil); !errors.As(pkg.Error, &missingErr) {
601 allMissingErrors = false
602 break
603 }
604 }
605 if haveErrors && allMissingErrors {
606 latestArgs := make([]string, len(args))
607 for i := range args {
608 latestArgs[i] = args[i] + "@latest"
609 }
610 hint := strings.Join(latestArgs, " ")
611 base.Fatalf("go install: version is required when current directory is not in a module\n\tTry 'go install %s' to install the latest version", hint)
612 }
613 }
614 load.CheckPackageErrors(pkgs)
615 if cfg.BuildI {
616 allGoroot := true
617 for _, pkg := range pkgs {
618 if !pkg.Goroot {
619 allGoroot = false
620 break
621 }
622 }
623 if !allGoroot {
624 fmt.Fprint(os.Stderr, "go install: -i flag is deprecated\n")
625 }
626 }
627
628 InstallPackages(ctx, args, pkgs)
629 }
630
631
632 func omitTestOnly(pkgs []*load.Package) []*load.Package {
633 var list []*load.Package
634 for _, p := range pkgs {
635 if len(p.GoFiles)+len(p.CgoFiles) == 0 && !p.Internal.CmdlinePkgLiteral {
636
637
638
639
640
641 continue
642 }
643 list = append(list, p)
644 }
645 return list
646 }
647
648 func InstallPackages(ctx context.Context, patterns []string, pkgs []*load.Package) {
649 ctx, span := trace.StartSpan(ctx, "InstallPackages "+strings.Join(patterns, " "))
650 defer span.Done()
651
652 if cfg.GOBIN != "" && !filepath.IsAbs(cfg.GOBIN) {
653 base.Fatalf("cannot install, GOBIN must be an absolute path")
654 }
655
656 pkgs = omitTestOnly(pkgsFilter(pkgs))
657 for _, p := range pkgs {
658 if p.Target == "" {
659 switch {
660 case p.Standard && p.ImportPath == "unsafe":
661
662 case p.Name != "main" && p.Internal.Local && p.ConflictDir == "":
663
664
665
666
667 case p.Name != "main" && p.Module != nil:
668
669 case p.Internal.GobinSubdir:
670 base.Errorf("go %s: cannot install cross-compiled binaries when GOBIN is set", cfg.CmdName)
671 case p.Internal.CmdlineFiles:
672 base.Errorf("go %s: no install location for .go files listed on command line (GOBIN not set)", cfg.CmdName)
673 case p.ConflictDir != "":
674 base.Errorf("go %s: no install location for %s: hidden by %s", cfg.CmdName, p.Dir, p.ConflictDir)
675 default:
676 base.Errorf("go %s: no install location for directory %s outside GOPATH\n"+
677 "\tFor more details see: 'go help gopath'", cfg.CmdName, p.Dir)
678 }
679 }
680 }
681 base.ExitIfErrors()
682
683 var b Builder
684 b.Init()
685 depMode := ModeBuild
686 if cfg.BuildI {
687 depMode = ModeInstall
688 }
689 a := &Action{Mode: "go install"}
690 var tools []*Action
691 for _, p := range pkgs {
692
693
694
695 a1 := b.AutoAction(ModeInstall, depMode, p)
696 if load.InstallTargetDir(p) == load.ToTool {
697 a.Deps = append(a.Deps, a1.Deps...)
698 a1.Deps = append(a1.Deps, a)
699 tools = append(tools, a1)
700 continue
701 }
702 a.Deps = append(a.Deps, a1)
703 }
704 if len(tools) > 0 {
705 a = &Action{
706 Mode: "go install (tools)",
707 Deps: tools,
708 }
709 }
710
711 if cfg.BuildBuildmode == "shared" {
712
713
714
715
716
717 a = b.buildmodeShared(ModeInstall, ModeInstall, patterns, pkgs, a)
718 }
719
720 b.Do(ctx, a)
721 base.ExitIfErrors()
722
723
724
725
726
727
728
729
730
731
732 if len(patterns) == 0 && len(pkgs) == 1 && pkgs[0].Name == "main" {
733
734
735 targ := pkgs[0].DefaultExecName()
736 targ += cfg.ExeSuffix
737 if filepath.Join(pkgs[0].Dir, targ) != pkgs[0].Target {
738 fi, err := os.Stat(targ)
739 if err == nil {
740 m := fi.Mode()
741 if m.IsRegular() {
742 if m&0111 != 0 || cfg.Goos == "windows" {
743 os.Remove(targ)
744 }
745 }
746 }
747 }
748 }
749 }
750
751
752
753
754
755
756 func installOutsideModule(ctx context.Context, args []string) {
757 modload.ForceUseModules = true
758 modload.RootMode = modload.NoRoot
759 modload.AllowMissingModuleImports()
760 modload.Init()
761 BuildInit()
762
763
764
765
766
767
768
769 pkgOpts := load.PackageOpts{MainOnly: true}
770 pkgs, err := load.PackagesAndErrorsOutsideModule(ctx, pkgOpts, args)
771 if err != nil {
772 base.Fatalf("go install: %v", err)
773 }
774 load.CheckPackageErrors(pkgs)
775 patterns := make([]string, len(args))
776 for i, arg := range args {
777 patterns[i] = arg[:strings.Index(arg, "@")]
778 }
779
780
781 InstallPackages(ctx, patterns, pkgs)
782 }
783
784
785
786
787
788
789
790 var ExecCmd []string
791
792
793
794 func FindExecCmd() []string {
795 if ExecCmd != nil {
796 return ExecCmd
797 }
798 ExecCmd = []string{}
799 if cfg.Goos == runtime.GOOS && cfg.Goarch == runtime.GOARCH {
800 return ExecCmd
801 }
802 path, err := exec.LookPath(fmt.Sprintf("go_%s_%s_exec", cfg.Goos, cfg.Goarch))
803 if err == nil {
804 ExecCmd = []string{path}
805 }
806 return ExecCmd
807 }
808
View as plain text