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

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

View as plain text