github.com/gagliardetto/golang-go@v0.0.0-20201020153340-53909ea70814/cmd/go/not-internal/work/build.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 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  	"github.com/gagliardetto/golang-go/cmd/go/not-internal/base"
    18  	"github.com/gagliardetto/golang-go/cmd/go/not-internal/cfg"
    19  	"github.com/gagliardetto/golang-go/cmd/go/not-internal/load"
    20  	"github.com/gagliardetto/golang-go/cmd/go/not-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, windows/amd64,
    66  		linux/ppc64le and linux/arm64 (only for 48-bit VMA).
    67  	-msan
    68  		enable interoperation with memory sanitizer.
    69  		Supported only on linux/amd64, linux/arm64
    70  		and only with Clang/LLVM as the host C compiler.
    71  		On linux/arm64, pie build mode will be used.
    72  	-v
    73  		print the names of packages as they are compiled.
    74  	-work
    75  		print the name of the temporary work directory and
    76  		do not delete it when exiting.
    77  	-x
    78  		print the commands.
    79  
    80  	-asmflags '[pattern=]arg list'
    81  		arguments to pass on each go tool asm invocation.
    82  	-buildmode mode
    83  		build mode to use. See 'go help buildmode' for more.
    84  	-compiler name
    85  		name of compiler to use, as in runtime.Compiler (gccgo or gc).
    86  	-gccgoflags '[pattern=]arg list'
    87  		arguments to pass on each gccgo compiler/linker invocation.
    88  	-gcflags '[pattern=]arg list'
    89  		arguments to pass on each go tool compile invocation.
    90  	-installsuffix suffix
    91  		a suffix to use in the name of the package installation directory,
    92  		in order to keep output separate from default builds.
    93  		If using the -race flag, the install suffix is automatically set to race
    94  		or, if set explicitly, has _race appended to it. Likewise for the -msan
    95  		flag. Using a -buildmode option that requires non-default compile flags
    96  		has a similar effect.
    97  	-ldflags '[pattern=]arg list'
    98  		arguments to pass on each go tool link invocation.
    99  	-linkshared
   100  		build code that will be linked against shared libraries previously
   101  		created with -buildmode=shared.
   102  	-mod mode
   103  		module download mode to use: readonly, vendor, or mod.
   104  		See 'go help modules' for more.
   105  	-modcacherw
   106  		leave newly-created directories in the module cache read-write
   107  		instead of making them read-only.
   108  	-modfile file
   109  		in module aware mode, read (and possibly write) an alternate go.mod
   110  		file instead of the one in the module root directory. A file named
   111  		"go.mod" must still be present in order to determine the module root
   112  		directory, but it is not accessed. When -modfile is specified, an
   113  		alternate go.sum file is also used: its path is derived from the
   114  		-modfile flag by trimming the ".mod" extension and appending ".sum".
   115  	-pkgdir dir
   116  		install and load all packages from dir instead of the usual locations.
   117  		For example, when building with a non-standard configuration,
   118  		use -pkgdir to keep generated packages in a separate location.
   119  	-tags tag,list
   120  		a comma-separated list of build tags to consider satisfied during the
   121  		build. For more information about build tags, see the description of
   122  		build constraints in the documentation for the go/build package.
   123  		(Earlier versions of Go used a space-separated list, and that form
   124  		is deprecated but still recognized.)
   125  	-trimpath
   126  		remove all file system paths from the resulting executable.
   127  		Instead of absolute file system paths, the recorded file names
   128  		will begin with either "go" (for the standard library),
   129  		or a module path@version (when using modules),
   130  		or a plain import path (when using GOPATH).
   131  	-toolexec 'cmd args'
   132  		a program to use to invoke toolchain programs like vet and asm.
   133  		For example, instead of running asm, the go command will run
   134  		'cmd args /path/to/asm <arguments for asm>'.
   135  
   136  The -asmflags, -gccgoflags, -gcflags, and -ldflags flags accept a
   137  space-separated list of arguments to pass to an underlying tool
   138  during the build. To embed spaces in an element in the list, surround
   139  it with either single or double quotes. The argument list may be
   140  preceded by a package pattern and an equal sign, which restricts
   141  the use of that argument list to the building of packages matching
   142  that pattern (see 'go help packages' for a description of package
   143  patterns). Without a pattern, the argument list applies only to the
   144  packages named on the command line. The flags may be repeated
   145  with different patterns in order to specify different arguments for
   146  different sets of packages. If a package matches patterns given in
   147  multiple flags, the latest match on the command line wins.
   148  For example, 'go build -gcflags=-S fmt' prints the disassembly
   149  only for package fmt, while 'go build -gcflags=all=-S fmt'
   150  prints the disassembly for fmt and all its dependencies.
   151  
   152  For more about specifying packages, see 'go help packages'.
   153  For more about where packages and binaries are installed,
   154  run 'go help gopath'.
   155  For more about calling between Go and C/C++, run 'go help c'.
   156  
   157  Note: Build adheres to certain conventions such as those described
   158  by 'go help gopath'. Not all projects can follow these conventions,
   159  however. Installations that have their own conventions or that use
   160  a separate software build system may choose to use lower-level
   161  invocations such as 'go tool compile' and 'go tool link' to avoid
   162  some of the overheads and design decisions of the build tool.
   163  
   164  See also: go install, go get, go clean.
   165  	`,
   166  }
   167  
   168  const concurrentGCBackendCompilationEnabledByDefault = true
   169  
   170  func init() {
   171  	// break init cycle
   172  	CmdBuild.Run = runBuild
   173  	CmdInstall.Run = runInstall
   174  
   175  	CmdBuild.Flag.BoolVar(&cfg.BuildI, "i", false, "")
   176  	CmdBuild.Flag.StringVar(&cfg.BuildO, "o", "", "output file or directory")
   177  
   178  	CmdInstall.Flag.BoolVar(&cfg.BuildI, "i", false, "")
   179  
   180  	AddBuildFlags(CmdBuild, DefaultBuildFlags)
   181  	AddBuildFlags(CmdInstall, DefaultBuildFlags)
   182  }
   183  
   184  // Note that flags consulted by other parts of the code
   185  // (for example, buildV) are in cmd/go/internal/cfg.
   186  
   187  var (
   188  	forcedAsmflags   []string // internally-forced flags for cmd/asm
   189  	forcedGcflags    []string // internally-forced flags for cmd/compile
   190  	forcedLdflags    []string // internally-forced flags for cmd/link
   191  	forcedGccgoflags []string // internally-forced flags for gccgo
   192  )
   193  
   194  var BuildToolchain toolchain = noToolchain{}
   195  var ldBuildmode string
   196  
   197  // buildCompiler implements flag.Var.
   198  // It implements Set by updating both
   199  // BuildToolchain and buildContext.Compiler.
   200  type buildCompiler struct{}
   201  
   202  func (c buildCompiler) Set(value string) error {
   203  	switch value {
   204  	case "gc":
   205  		BuildToolchain = gcToolchain{}
   206  	case "gccgo":
   207  		BuildToolchain = gccgoToolchain{}
   208  	default:
   209  		return fmt.Errorf("unknown compiler %q", value)
   210  	}
   211  	cfg.BuildToolchainName = value
   212  	cfg.BuildToolchainCompiler = BuildToolchain.compiler
   213  	cfg.BuildToolchainLinker = BuildToolchain.linker
   214  	cfg.BuildContext.Compiler = value
   215  	return nil
   216  }
   217  
   218  func (c buildCompiler) String() string {
   219  	return cfg.BuildContext.Compiler
   220  }
   221  
   222  func init() {
   223  	switch build.Default.Compiler {
   224  	case "gc", "gccgo":
   225  		buildCompiler{}.Set(build.Default.Compiler)
   226  	}
   227  }
   228  
   229  type BuildFlagMask int
   230  
   231  const (
   232  	DefaultBuildFlags BuildFlagMask = 0
   233  	OmitModFlag       BuildFlagMask = 1 << iota
   234  	OmitModCommonFlags
   235  )
   236  
   237  // AddBuildFlags adds the flags common to the build, clean, get,
   238  // install, list, run, and test commands.
   239  func AddBuildFlags(cmd *base.Command, mask BuildFlagMask) {
   240  	cmd.Flag.BoolVar(&cfg.BuildA, "a", false, "")
   241  	cmd.Flag.BoolVar(&cfg.BuildN, "n", false, "")
   242  	cmd.Flag.IntVar(&cfg.BuildP, "p", cfg.BuildP, "")
   243  	cmd.Flag.BoolVar(&cfg.BuildV, "v", false, "")
   244  	cmd.Flag.BoolVar(&cfg.BuildX, "x", false, "")
   245  
   246  	cmd.Flag.Var(&load.BuildAsmflags, "asmflags", "")
   247  	cmd.Flag.Var(buildCompiler{}, "compiler", "")
   248  	cmd.Flag.StringVar(&cfg.BuildBuildmode, "buildmode", "default", "")
   249  	cmd.Flag.Var(&load.BuildGcflags, "gcflags", "")
   250  	cmd.Flag.Var(&load.BuildGccgoflags, "gccgoflags", "")
   251  	if mask&OmitModFlag == 0 {
   252  		cmd.Flag.StringVar(&cfg.BuildMod, "mod", "", "")
   253  	}
   254  	if mask&OmitModCommonFlags == 0 {
   255  		AddModCommonFlags(cmd)
   256  	}
   257  	cmd.Flag.StringVar(&cfg.BuildContext.InstallSuffix, "installsuffix", "", "")
   258  	cmd.Flag.Var(&load.BuildLdflags, "ldflags", "")
   259  	cmd.Flag.BoolVar(&cfg.BuildLinkshared, "linkshared", false, "")
   260  	cmd.Flag.StringVar(&cfg.BuildPkgdir, "pkgdir", "", "")
   261  	cmd.Flag.BoolVar(&cfg.BuildRace, "race", false, "")
   262  	cmd.Flag.BoolVar(&cfg.BuildMSan, "msan", false, "")
   263  	cmd.Flag.Var((*tagsFlag)(&cfg.BuildContext.BuildTags), "tags", "")
   264  	cmd.Flag.Var((*base.StringsFlag)(&cfg.BuildToolexec), "toolexec", "")
   265  	cmd.Flag.BoolVar(&cfg.BuildTrimpath, "trimpath", false, "")
   266  	cmd.Flag.BoolVar(&cfg.BuildWork, "work", false, "")
   267  
   268  	// Undocumented, unstable debugging flags.
   269  	cmd.Flag.StringVar(&cfg.DebugActiongraph, "debug-actiongraph", "", "")
   270  }
   271  
   272  // AddModCommonFlags adds the module-related flags common to build commands
   273  // and 'go mod' subcommands.
   274  func AddModCommonFlags(cmd *base.Command) {
   275  	cmd.Flag.BoolVar(&cfg.ModCacheRW, "modcacherw", false, "")
   276  	cmd.Flag.StringVar(&cfg.ModFile, "modfile", "", "")
   277  }
   278  
   279  // tagsFlag is the implementation of the -tags flag.
   280  type tagsFlag []string
   281  
   282  func (v *tagsFlag) Set(s string) error {
   283  	// For compatibility with Go 1.12 and earlier, allow "-tags='a b c'" or even just "-tags='a'".
   284  	if strings.Contains(s, " ") || strings.Contains(s, "'") {
   285  		return (*base.StringsFlag)(v).Set(s)
   286  	}
   287  
   288  	// Split on commas, ignore empty strings.
   289  	*v = []string{}
   290  	for _, s := range strings.Split(s, ",") {
   291  		if s != "" {
   292  			*v = append(*v, s)
   293  		}
   294  	}
   295  	return nil
   296  }
   297  
   298  func (v *tagsFlag) String() string {
   299  	return "<TagsFlag>"
   300  }
   301  
   302  // fileExtSplit expects a filename and returns the name
   303  // and ext (without the dot). If the file has no
   304  // extension, ext will be empty.
   305  func fileExtSplit(file string) (name, ext string) {
   306  	dotExt := filepath.Ext(file)
   307  	name = file[:len(file)-len(dotExt)]
   308  	if dotExt != "" {
   309  		ext = dotExt[1:]
   310  	}
   311  	return
   312  }
   313  
   314  func pkgsMain(pkgs []*load.Package) (res []*load.Package) {
   315  	for _, p := range pkgs {
   316  		if p.Name == "main" {
   317  			res = append(res, p)
   318  		}
   319  	}
   320  	return res
   321  }
   322  
   323  func pkgsNotMain(pkgs []*load.Package) (res []*load.Package) {
   324  	for _, p := range pkgs {
   325  		if p.Name != "main" {
   326  			res = append(res, p)
   327  		}
   328  	}
   329  	return res
   330  }
   331  
   332  func oneMainPkg(pkgs []*load.Package) []*load.Package {
   333  	if len(pkgs) != 1 || pkgs[0].Name != "main" {
   334  		base.Fatalf("-buildmode=%s requires exactly one main package", cfg.BuildBuildmode)
   335  	}
   336  	return pkgs
   337  }
   338  
   339  var pkgsFilter = func(pkgs []*load.Package) []*load.Package { return pkgs }
   340  
   341  var runtimeVersion = runtime.Version()
   342  
   343  func runBuild(cmd *base.Command, args []string) {
   344  	BuildInit()
   345  	var b Builder
   346  	b.Init()
   347  
   348  	pkgs := load.PackagesForBuild(args)
   349  
   350  	explicitO := len(cfg.BuildO) > 0
   351  
   352  	if len(pkgs) == 1 && pkgs[0].Name == "main" && cfg.BuildO == "" {
   353  		cfg.BuildO = pkgs[0].DefaultExecName()
   354  		cfg.BuildO += cfg.ExeSuffix
   355  	}
   356  
   357  	// sanity check some often mis-used options
   358  	switch cfg.BuildContext.Compiler {
   359  	case "gccgo":
   360  		if load.BuildGcflags.Present() {
   361  			fmt.Println("go build: when using gccgo toolchain, please pass compiler flags using -gccgoflags, not -gcflags")
   362  		}
   363  		if load.BuildLdflags.Present() {
   364  			fmt.Println("go build: when using gccgo toolchain, please pass linker flags using -gccgoflags, not -ldflags")
   365  		}
   366  	case "gc":
   367  		if load.BuildGccgoflags.Present() {
   368  			fmt.Println("go build: when using gc toolchain, please pass compile flags using -gcflags, and linker flags using -ldflags")
   369  		}
   370  	}
   371  
   372  	depMode := ModeBuild
   373  	if cfg.BuildI {
   374  		depMode = ModeInstall
   375  	}
   376  
   377  	pkgs = omitTestOnly(pkgsFilter(load.Packages(args)))
   378  
   379  	// Special case -o /dev/null by not writing at all.
   380  	if cfg.BuildO == os.DevNull {
   381  		cfg.BuildO = ""
   382  	}
   383  
   384  	if cfg.BuildO != "" {
   385  		// If the -o name exists and is a directory, then
   386  		// write all main packages to that directory.
   387  		// Otherwise require only a single package be built.
   388  		if fi, err := os.Stat(cfg.BuildO); err == nil && fi.IsDir() {
   389  			if !explicitO {
   390  				base.Fatalf("go build: build output %q already exists and is a directory", cfg.BuildO)
   391  			}
   392  			a := &Action{Mode: "go build"}
   393  			for _, p := range pkgs {
   394  				if p.Name != "main" {
   395  					continue
   396  				}
   397  
   398  				p.Target = filepath.Join(cfg.BuildO, p.DefaultExecName())
   399  				p.Target += cfg.ExeSuffix
   400  				p.Stale = true
   401  				p.StaleReason = "build -o flag in use"
   402  				a.Deps = append(a.Deps, b.AutoAction(ModeInstall, depMode, p))
   403  			}
   404  			if len(a.Deps) == 0 {
   405  				base.Fatalf("go build: no main packages to build")
   406  			}
   407  			b.Do(a)
   408  			return
   409  		}
   410  		if len(pkgs) > 1 {
   411  			base.Fatalf("go build: cannot write multiple packages to non-directory %s", cfg.BuildO)
   412  		} else if len(pkgs) == 0 {
   413  			base.Fatalf("no packages to build")
   414  		}
   415  		p := pkgs[0]
   416  		p.Target = cfg.BuildO
   417  		p.Stale = true // must build - not up to date
   418  		p.StaleReason = "build -o flag in use"
   419  		a := b.AutoAction(ModeInstall, depMode, p)
   420  		b.Do(a)
   421  		return
   422  	}
   423  
   424  	a := &Action{Mode: "go build"}
   425  	for _, p := range pkgs {
   426  		a.Deps = append(a.Deps, b.AutoAction(ModeBuild, depMode, p))
   427  	}
   428  	if cfg.BuildBuildmode == "shared" {
   429  		a = b.buildmodeShared(ModeBuild, depMode, args, pkgs, a)
   430  	}
   431  	b.Do(a)
   432  }
   433  
   434  var CmdInstall = &base.Command{
   435  	UsageLine: "go install [-i] [build flags] [packages]",
   436  	Short:     "compile and install packages and dependencies",
   437  	Long: `
   438  Install compiles and installs the packages named by the import paths.
   439  
   440  Executables are installed in the directory named by the GOBIN environment
   441  variable, which defaults to $GOPATH/bin or $HOME/go/bin if the GOPATH
   442  environment variable is not set. Executables in $GOROOT
   443  are installed in $GOROOT/bin or $GOTOOLDIR instead of $GOBIN.
   444  
   445  When module-aware mode is disabled, other packages are installed in the
   446  directory $GOPATH/pkg/$GOOS_$GOARCH. When module-aware mode is enabled,
   447  other packages are built and cached but not installed.
   448  
   449  The -i flag installs the dependencies of the named packages as well.
   450  
   451  For more about the build flags, see 'go help build'.
   452  For more about specifying packages, see 'go help packages'.
   453  
   454  See also: go build, go get, go clean.
   455  	`,
   456  }
   457  
   458  // libname returns the filename to use for the shared library when using
   459  // -buildmode=shared. The rules we use are:
   460  // Use arguments for special 'meta' packages:
   461  //	std --> libstd.so
   462  //	std cmd --> libstd,cmd.so
   463  // A single non-meta argument with trailing "/..." is special cased:
   464  //	foo/... --> libfoo.so
   465  //	(A relative path like "./..."  expands the "." first)
   466  // Use import paths for other cases, changing '/' to '-':
   467  //	somelib --> libsubdir-somelib.so
   468  //	./ or ../ --> libsubdir-somelib.so
   469  //	gopkg.in/tomb.v2 -> libgopkg.in-tomb.v2.so
   470  //	a/... b/... ---> liba/c,b/d.so - all matching import paths
   471  // Name parts are joined with ','.
   472  func libname(args []string, pkgs []*load.Package) (string, error) {
   473  	var libname string
   474  	appendName := func(arg string) {
   475  		if libname == "" {
   476  			libname = arg
   477  		} else {
   478  			libname += "," + arg
   479  		}
   480  	}
   481  	var haveNonMeta bool
   482  	for _, arg := range args {
   483  		if search.IsMetaPackage(arg) {
   484  			appendName(arg)
   485  		} else {
   486  			haveNonMeta = true
   487  		}
   488  	}
   489  	if len(libname) == 0 { // non-meta packages only. use import paths
   490  		if len(args) == 1 && strings.HasSuffix(args[0], "/...") {
   491  			// Special case of "foo/..." as mentioned above.
   492  			arg := strings.TrimSuffix(args[0], "/...")
   493  			if build.IsLocalImport(arg) {
   494  				cwd, _ := os.Getwd()
   495  				bp, _ := cfg.BuildContext.ImportDir(filepath.Join(cwd, arg), build.FindOnly)
   496  				if bp.ImportPath != "" && bp.ImportPath != "." {
   497  					arg = bp.ImportPath
   498  				}
   499  			}
   500  			appendName(strings.ReplaceAll(arg, "/", "-"))
   501  		} else {
   502  			for _, pkg := range pkgs {
   503  				appendName(strings.ReplaceAll(pkg.ImportPath, "/", "-"))
   504  			}
   505  		}
   506  	} else if haveNonMeta { // have both meta package and a non-meta one
   507  		return "", errors.New("mixing of meta and non-meta packages is not allowed")
   508  	}
   509  	// TODO(mwhudson): Needs to change for platforms that use different naming
   510  	// conventions...
   511  	return "lib" + libname + ".so", nil
   512  }
   513  
   514  func runInstall(cmd *base.Command, args []string) {
   515  	BuildInit()
   516  	InstallPackages(args, load.PackagesForBuild(args))
   517  }
   518  
   519  // omitTestOnly returns pkgs with test-only packages removed.
   520  func omitTestOnly(pkgs []*load.Package) []*load.Package {
   521  	var list []*load.Package
   522  	for _, p := range pkgs {
   523  		if len(p.GoFiles)+len(p.CgoFiles) == 0 && !p.Internal.CmdlinePkgLiteral {
   524  			// Package has no source files,
   525  			// perhaps due to build tags or perhaps due to only having *_test.go files.
   526  			// Also, it is only being processed as the result of a wildcard match
   527  			// like ./..., not because it was listed as a literal path on the command line.
   528  			// Ignore it.
   529  			continue
   530  		}
   531  		list = append(list, p)
   532  	}
   533  	return list
   534  }
   535  
   536  func InstallPackages(patterns []string, pkgs []*load.Package) {
   537  	if cfg.GOBIN != "" && !filepath.IsAbs(cfg.GOBIN) {
   538  		base.Fatalf("cannot install, GOBIN must be an absolute path")
   539  	}
   540  
   541  	pkgs = omitTestOnly(pkgsFilter(pkgs))
   542  	for _, p := range pkgs {
   543  		if p.Target == "" {
   544  			switch {
   545  			case p.Standard && p.ImportPath == "unsafe":
   546  				// unsafe is a built-in package, has no target
   547  			case p.Name != "main" && p.Internal.Local && p.ConflictDir == "":
   548  				// Non-executables outside GOPATH need not have a target:
   549  				// we can use the cache to hold the built package archive for use in future builds.
   550  				// The ones inside GOPATH should have a target (in GOPATH/pkg)
   551  				// or else something is wrong and worth reporting (like a ConflictDir).
   552  			case p.Name != "main" && p.Module != nil:
   553  				// Non-executables have no target (except the cache) when building with modules.
   554  			case p.Internal.GobinSubdir:
   555  				base.Errorf("go %s: cannot install cross-compiled binaries when GOBIN is set", cfg.CmdName)
   556  			case p.Internal.CmdlineFiles:
   557  				base.Errorf("go %s: no install location for .go files listed on command line (GOBIN not set)", cfg.CmdName)
   558  			case p.ConflictDir != "":
   559  				base.Errorf("go %s: no install location for %s: hidden by %s", cfg.CmdName, p.Dir, p.ConflictDir)
   560  			default:
   561  				base.Errorf("go %s: no install location for directory %s outside GOPATH\n"+
   562  					"\tFor more details see: 'go help gopath'", cfg.CmdName, p.Dir)
   563  			}
   564  		}
   565  	}
   566  	base.ExitIfErrors()
   567  
   568  	var b Builder
   569  	b.Init()
   570  	depMode := ModeBuild
   571  	if cfg.BuildI {
   572  		depMode = ModeInstall
   573  	}
   574  	a := &Action{Mode: "go install"}
   575  	var tools []*Action
   576  	for _, p := range pkgs {
   577  		// If p is a tool, delay the installation until the end of the build.
   578  		// This avoids installing assemblers/compilers that are being executed
   579  		// by other steps in the build.
   580  		a1 := b.AutoAction(ModeInstall, depMode, p)
   581  		if load.InstallTargetDir(p) == load.ToTool {
   582  			a.Deps = append(a.Deps, a1.Deps...)
   583  			a1.Deps = append(a1.Deps, a)
   584  			tools = append(tools, a1)
   585  			continue
   586  		}
   587  		a.Deps = append(a.Deps, a1)
   588  	}
   589  	if len(tools) > 0 {
   590  		a = &Action{
   591  			Mode: "go install (tools)",
   592  			Deps: tools,
   593  		}
   594  	}
   595  
   596  	if cfg.BuildBuildmode == "shared" {
   597  		// Note: If buildmode=shared then only non-main packages
   598  		// are present in the pkgs list, so all the special case code about
   599  		// tools above did not apply, and a is just a simple Action
   600  		// with a list of Deps, one per package named in pkgs,
   601  		// the same as in runBuild.
   602  		a = b.buildmodeShared(ModeInstall, ModeInstall, patterns, pkgs, a)
   603  	}
   604  
   605  	b.Do(a)
   606  	base.ExitIfErrors()
   607  
   608  	// Success. If this command is 'go install' with no arguments
   609  	// and the current directory (the implicit argument) is a command,
   610  	// remove any leftover command binary from a previous 'go build'.
   611  	// The binary is installed; it's not needed here anymore.
   612  	// And worse it might be a stale copy, which you don't want to find
   613  	// instead of the installed one if $PATH contains dot.
   614  	// One way to view this behavior is that it is as if 'go install' first
   615  	// runs 'go build' and the moves the generated file to the install dir.
   616  	// See issue 9645.
   617  	if len(patterns) == 0 && len(pkgs) == 1 && pkgs[0].Name == "main" {
   618  		// Compute file 'go build' would have created.
   619  		// If it exists and is an executable file, remove it.
   620  		targ := pkgs[0].DefaultExecName()
   621  		targ += cfg.ExeSuffix
   622  		if filepath.Join(pkgs[0].Dir, targ) != pkgs[0].Target { // maybe $GOBIN is the current directory
   623  			fi, err := os.Stat(targ)
   624  			if err == nil {
   625  				m := fi.Mode()
   626  				if m.IsRegular() {
   627  					if m&0111 != 0 || cfg.Goos == "windows" { // windows never sets executable bit
   628  						os.Remove(targ)
   629  					}
   630  				}
   631  			}
   632  		}
   633  	}
   634  }
   635  
   636  // ExecCmd is the command to use to run user binaries.
   637  // Normally it is empty, meaning run the binaries directly.
   638  // If cross-compiling and running on a remote system or
   639  // simulator, it is typically go_GOOS_GOARCH_exec, with
   640  // the target GOOS and GOARCH substituted.
   641  // The -exec flag overrides these defaults.
   642  var ExecCmd []string
   643  
   644  // FindExecCmd derives the value of ExecCmd to use.
   645  // It returns that value and leaves ExecCmd set for direct use.
   646  func FindExecCmd() []string {
   647  	if ExecCmd != nil {
   648  		return ExecCmd
   649  	}
   650  	ExecCmd = []string{} // avoid work the second time
   651  	if cfg.Goos == runtime.GOOS && cfg.Goarch == runtime.GOARCH {
   652  		return ExecCmd
   653  	}
   654  	path, err := exec.LookPath(fmt.Sprintf("go_%s_%s_exec", cfg.Goos, cfg.Goarch))
   655  	if err == nil {
   656  		ExecCmd = []string{path}
   657  	}
   658  	return ExecCmd
   659  }