github.com/zxy12/go_duplicate_112_new@v0.0.0-20200807091221-747231827200/src/cmd/go/internal/cfg/cfg.go (about)

     1  // Copyright 2017 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 cfg holds configuration shared by multiple parts
     6  // of the go command.
     7  package cfg
     8  
     9  import (
    10  	"fmt"
    11  	"go/build"
    12  	"os"
    13  	"path/filepath"
    14  	"runtime"
    15  
    16  	"cmd/internal/objabi"
    17  )
    18  
    19  // These are general "build flags" used by build and other commands.
    20  var (
    21  	BuildA                 bool   // -a flag
    22  	BuildBuildmode         string // -buildmode flag
    23  	BuildContext           = defaultContext()
    24  	BuildMod               string             // -mod flag
    25  	BuildI                 bool               // -i flag
    26  	BuildLinkshared        bool               // -linkshared flag
    27  	BuildMSan              bool               // -msan flag
    28  	BuildN                 bool               // -n flag
    29  	BuildO                 string             // -o flag
    30  	BuildP                 = runtime.NumCPU() // -p flag
    31  	BuildPkgdir            string             // -pkgdir flag
    32  	BuildRace              bool               // -race flag
    33  	BuildToolexec          []string           // -toolexec flag
    34  	BuildToolchainName     string
    35  	BuildToolchainCompiler func() string
    36  	BuildToolchainLinker   func() string
    37  	BuildV                 bool // -v flag
    38  	BuildWork              bool // -work flag
    39  	BuildX                 bool // -x flag
    40  
    41  	CmdName string // "build", "install", "list", etc.
    42  
    43  	DebugActiongraph string // -debug-actiongraph flag (undocumented, unstable)
    44  )
    45  
    46  func defaultContext() build.Context {
    47  	ctxt := build.Default
    48  	ctxt.JoinPath = filepath.Join // back door to say "do not use go command"
    49  	return ctxt
    50  }
    51  
    52  func init() {
    53  	BuildToolchainCompiler = func() string { return "missing-compiler" }
    54  	BuildToolchainLinker = func() string { return "missing-linker" }
    55  }
    56  
    57  // An EnvVar is an environment variable Name=Value.
    58  type EnvVar struct {
    59  	Name  string
    60  	Value string
    61  }
    62  
    63  // OrigEnv is the original environment of the program at startup.
    64  var OrigEnv []string
    65  
    66  // CmdEnv is the new environment for running go tool commands.
    67  // User binaries (during go test or go run) are run with OrigEnv,
    68  // not CmdEnv.
    69  var CmdEnv []EnvVar
    70  
    71  // Global build parameters (used during package load)
    72  var (
    73  	Goarch    = BuildContext.GOARCH
    74  	Goos      = BuildContext.GOOS
    75  	ExeSuffix string
    76  	Gopath    = filepath.SplitList(BuildContext.GOPATH)
    77  
    78  	// ModulesEnabled specifies whether the go command is running
    79  	// in module-aware mode (as opposed to GOPATH mode).
    80  	// It is equal to modload.Enabled, but not all packages can import modload.
    81  	ModulesEnabled bool
    82  
    83  	// GoModInGOPATH records whether we've found a go.mod in GOPATH/src
    84  	// in GO111MODULE=auto mode. In that case, we don't use modules
    85  	// but people might expect us to, so 'go get' warns.
    86  	GoModInGOPATH string
    87  )
    88  
    89  func init() {
    90  	if Goos == "windows" {
    91  		ExeSuffix = ".exe"
    92  	}
    93  }
    94  
    95  var (
    96  	GOROOT       = findGOROOT()
    97  	GOBIN        = os.Getenv("GOBIN")
    98  	GOROOTbin    = filepath.Join(GOROOT, "bin")
    99  	GOROOTpkg    = filepath.Join(GOROOT, "pkg")
   100  	GOROOTsrc    = filepath.Join(GOROOT, "src")
   101  	GOROOT_FINAL = findGOROOT_FINAL()
   102  
   103  	// Used in envcmd.MkEnv and build ID computations.
   104  	GOARM    = fmt.Sprint(objabi.GOARM)
   105  	GO386    = objabi.GO386
   106  	GOMIPS   = objabi.GOMIPS
   107  	GOMIPS64 = objabi.GOMIPS64
   108  )
   109  
   110  // Update build context to use our computed GOROOT.
   111  func init() {
   112  	BuildContext.GOROOT = GOROOT
   113  	if runtime.Compiler != "gccgo" {
   114  		// Note that we must use runtime.GOOS and runtime.GOARCH here,
   115  		// as the tool directory does not move based on environment
   116  		// variables. This matches the initialization of ToolDir in
   117  		// go/build, except for using GOROOT rather than
   118  		// runtime.GOROOT.
   119  		build.ToolDir = filepath.Join(GOROOT, "pkg/tool/"+runtime.GOOS+"_"+runtime.GOARCH)
   120  	}
   121  }
   122  
   123  // There is a copy of findGOROOT, isSameDir, and isGOROOT in
   124  // x/tools/cmd/godoc/goroot.go.
   125  // Try to keep them in sync for now.
   126  
   127  // findGOROOT returns the GOROOT value, using either an explicitly
   128  // provided environment variable, a GOROOT that contains the current
   129  // os.Executable value, or else the GOROOT that the binary was built
   130  // with from runtime.GOROOT().
   131  //
   132  // There is a copy of this code in x/tools/cmd/godoc/goroot.go.
   133  func findGOROOT() string {
   134  	if env := os.Getenv("GOROOT"); env != "" {
   135  		return filepath.Clean(env)
   136  	}
   137  	def := filepath.Clean(runtime.GOROOT())
   138  	if runtime.Compiler == "gccgo" {
   139  		// gccgo has no real GOROOT, and it certainly doesn't
   140  		// depend on the executable's location.
   141  		return def
   142  	}
   143  	exe, err := os.Executable()
   144  	if err == nil {
   145  		exe, err = filepath.Abs(exe)
   146  		if err == nil {
   147  			if dir := filepath.Join(exe, "../.."); isGOROOT(dir) {
   148  				// If def (runtime.GOROOT()) and dir are the same
   149  				// directory, prefer the spelling used in def.
   150  				if isSameDir(def, dir) {
   151  					return def
   152  				}
   153  				return dir
   154  			}
   155  			exe, err = filepath.EvalSymlinks(exe)
   156  			if err == nil {
   157  				if dir := filepath.Join(exe, "../.."); isGOROOT(dir) {
   158  					if isSameDir(def, dir) {
   159  						return def
   160  					}
   161  					return dir
   162  				}
   163  			}
   164  		}
   165  	}
   166  	return def
   167  }
   168  
   169  func findGOROOT_FINAL() string {
   170  	def := GOROOT
   171  	if env := os.Getenv("GOROOT_FINAL"); env != "" {
   172  		def = filepath.Clean(env)
   173  	}
   174  	return def
   175  }
   176  
   177  // isSameDir reports whether dir1 and dir2 are the same directory.
   178  func isSameDir(dir1, dir2 string) bool {
   179  	if dir1 == dir2 {
   180  		return true
   181  	}
   182  	info1, err1 := os.Stat(dir1)
   183  	info2, err2 := os.Stat(dir2)
   184  	return err1 == nil && err2 == nil && os.SameFile(info1, info2)
   185  }
   186  
   187  // isGOROOT reports whether path looks like a GOROOT.
   188  //
   189  // It does this by looking for the path/pkg/tool directory,
   190  // which is necessary for useful operation of the cmd/go tool,
   191  // and is not typically present in a GOPATH.
   192  //
   193  // There is a copy of this code in x/tools/cmd/godoc/goroot.go.
   194  func isGOROOT(path string) bool {
   195  	stat, err := os.Stat(filepath.Join(path, "pkg", "tool"))
   196  	if err != nil {
   197  		return false
   198  	}
   199  	return stat.IsDir()
   200  }