Black Lives Matter. Support the Equal Justice Initiative.

Source file src/cmd/go/internal/work/build.go

Documentation: cmd/go/internal/work

     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  	"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  	// break init cycle
   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  // Note that flags consulted by other parts of the code
   207  // (for example, buildV) are in cmd/go/internal/cfg.
   208  
   209  var (
   210  	forcedAsmflags   []string // internally-forced flags for cmd/asm
   211  	forcedGcflags    []string // internally-forced flags for cmd/compile
   212  	forcedLdflags    []string // internally-forced flags for cmd/link
   213  	forcedGccgoflags []string // internally-forced flags for gccgo
   214  )
   215  
   216  var BuildToolchain toolchain = noToolchain{}
   217  var ldBuildmode string
   218  
   219  // buildCompiler implements flag.Var.
   220  // It implements Set by updating both
   221  // BuildToolchain and buildContext.Compiler.
   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  // AddBuildFlags adds the flags common to the build, clean, get,
   261  // install, list, run, and test commands.
   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  		// Add the overlay flag even when we don't add the rest of the mod common flags.
   282  		// This only affects 'go get' in GOPATH mode, but add the flag anyway for
   283  		// consistency.
   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  	// Undocumented, unstable debugging flags.
   298  	cmd.Flag.StringVar(&cfg.DebugActiongraph, "debug-actiongraph", "", "")
   299  	cmd.Flag.StringVar(&cfg.DebugTrace, "debug-trace", "", "")
   300  }
   301  
   302  // tagsFlag is the implementation of the -tags flag.
   303  type tagsFlag []string
   304  
   305  func (v *tagsFlag) Set(s string) error {
   306  	// For compatibility with Go 1.12 and earlier, allow "-tags='a b c'" or even just "-tags='a'".
   307  	if strings.Contains(s, " ") || strings.Contains(s, "'") {
   308  		return (*base.StringsFlag)(v).Set(s)
   309  	}
   310  
   311  	// Split on commas, ignore empty strings.
   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  // fileExtSplit expects a filename and returns the name
   326  // and ext (without the dot). If the file has no
   327  // extension, ext will be empty.
   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  	// sanity check some often mis-used options
   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  	// Special case -o /dev/null by not writing at all.
   405  	if cfg.BuildO == os.DevNull {
   406  		cfg.BuildO = ""
   407  	}
   408  
   409  	if cfg.BuildO != "" {
   410  		// If the -o name exists and is a directory or
   411  		// ends with a slash or backslash, then
   412  		// write all main packages to that directory.
   413  		// Otherwise require only a single package be built.
   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 // must build - not up to date
   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  // libname returns the filename to use for the shared library when using
   519  // -buildmode=shared. The rules we use are:
   520  // Use arguments for special 'meta' packages:
   521  //	std --> libstd.so
   522  //	std cmd --> libstd,cmd.so
   523  // A single non-meta argument with trailing "/..." is special cased:
   524  //	foo/... --> libfoo.so
   525  //	(A relative path like "./..."  expands the "." first)
   526  // Use import paths for other cases, changing '/' to '-':
   527  //	somelib --> libsubdir-somelib.so
   528  //	./ or ../ --> libsubdir-somelib.so
   529  //	gopkg.in/tomb.v2 -> libgopkg.in-tomb.v2.so
   530  //	a/... b/... ---> liba/c,b/d.so - all matching import paths
   531  // Name parts are joined with ','.
   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 { // non-meta packages only. use import paths
   550  		if len(args) == 1 && strings.HasSuffix(args[0], "/...") {
   551  			// Special case of "foo/..." as mentioned above.
   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 { // have both meta package and a non-meta one
   567  		return "", errors.New("mixing of meta and non-meta packages is not allowed")
   568  	}
   569  	// TODO(mwhudson): Needs to change for platforms that use different naming
   570  	// conventions...
   571  	return "lib" + libname + ".so", nil
   572  }
   573  
   574  func runInstall(ctx context.Context, cmd *base.Command, args []string) {
   575  	// TODO(golang.org/issue/41696): print a deprecation message for the -i flag
   576  	// whenever it's set (or just remove it). For now, we don't print a message
   577  	// if all named packages are in GOROOT. cmd/dist (run by make.bash) uses
   578  	// 'go install -i' when bootstrapping, and we don't want to show deprecation
   579  	// messages in that case.
   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  // omitTestOnly returns pkgs with test-only packages removed.
   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  			// Package has no source files,
   637  			// perhaps due to build tags or perhaps due to only having *_test.go files.
   638  			// Also, it is only being processed as the result of a wildcard match
   639  			// like ./..., not because it was listed as a literal path on the command line.
   640  			// Ignore it.
   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  				// unsafe is a built-in package, has no target
   662  			case p.Name != "main" && p.Internal.Local && p.ConflictDir == "":
   663  				// Non-executables outside GOPATH need not have a target:
   664  				// we can use the cache to hold the built package archive for use in future builds.
   665  				// The ones inside GOPATH should have a target (in GOPATH/pkg)
   666  				// or else something is wrong and worth reporting (like a ConflictDir).
   667  			case p.Name != "main" && p.Module != nil:
   668  				// Non-executables have no target (except the cache) when building with modules.
   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  		// If p is a tool, delay the installation until the end of the build.
   693  		// This avoids installing assemblers/compilers that are being executed
   694  		// by other steps in the build.
   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  		// Note: If buildmode=shared then only non-main packages
   713  		// are present in the pkgs list, so all the special case code about
   714  		// tools above did not apply, and a is just a simple Action
   715  		// with a list of Deps, one per package named in pkgs,
   716  		// the same as in runBuild.
   717  		a = b.buildmodeShared(ModeInstall, ModeInstall, patterns, pkgs, a)
   718  	}
   719  
   720  	b.Do(ctx, a)
   721  	base.ExitIfErrors()
   722  
   723  	// Success. If this command is 'go install' with no arguments
   724  	// and the current directory (the implicit argument) is a command,
   725  	// remove any leftover command binary from a previous 'go build'.
   726  	// The binary is installed; it's not needed here anymore.
   727  	// And worse it might be a stale copy, which you don't want to find
   728  	// instead of the installed one if $PATH contains dot.
   729  	// One way to view this behavior is that it is as if 'go install' first
   730  	// runs 'go build' and the moves the generated file to the install dir.
   731  	// See issue 9645.
   732  	if len(patterns) == 0 && len(pkgs) == 1 && pkgs[0].Name == "main" {
   733  		// Compute file 'go build' would have created.
   734  		// If it exists and is an executable file, remove it.
   735  		targ := pkgs[0].DefaultExecName()
   736  		targ += cfg.ExeSuffix
   737  		if filepath.Join(pkgs[0].Dir, targ) != pkgs[0].Target { // maybe $GOBIN is the current directory
   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" { // windows never sets executable bit
   743  						os.Remove(targ)
   744  					}
   745  				}
   746  			}
   747  		}
   748  	}
   749  }
   750  
   751  // installOutsideModule implements 'go install pkg@version'. It builds and
   752  // installs one or more main packages in module mode while ignoring any go.mod
   753  // in the current directory or parent directories.
   754  //
   755  // See golang.org/issue/40276 for details and rationale.
   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  	// Load packages. Ignore non-main packages.
   764  	// Print a warning if an argument contains "..." and matches no main packages.
   765  	// PackagesAndErrors already prints warnings for patterns that don't match any
   766  	// packages, so be careful not to double print.
   767  	// TODO(golang.org/issue/40276): don't report errors loading non-main packages
   768  	// matched by a pattern.
   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  	// Build and install the packages.
   781  	InstallPackages(ctx, patterns, pkgs)
   782  }
   783  
   784  // ExecCmd is the command to use to run user binaries.
   785  // Normally it is empty, meaning run the binaries directly.
   786  // If cross-compiling and running on a remote system or
   787  // simulator, it is typically go_GOOS_GOARCH_exec, with
   788  // the target GOOS and GOARCH substituted.
   789  // The -exec flag overrides these defaults.
   790  var ExecCmd []string
   791  
   792  // FindExecCmd derives the value of ExecCmd to use.
   793  // It returns that value and leaves ExecCmd set for direct use.
   794  func FindExecCmd() []string {
   795  	if ExecCmd != nil {
   796  		return ExecCmd
   797  	}
   798  	ExecCmd = []string{} // avoid work the second time
   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