github.com/JimmyHuang454/JLS-go@v0.0.0-20230831150107-90d536585ba0/internal/buildcfg/cfg.go (about)

     1  // Copyright 2021 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 buildcfg provides access to the build configuration
     6  // described by the current environment. It is for use by build tools
     7  // such as cmd/go or cmd/compile and for setting up go/build's Default context.
     8  //
     9  // Note that it does NOT provide access to the build configuration used to
    10  // build the currently-running binary. For that, use runtime.GOOS etc
    11  // as well as internal/goexperiment.
    12  package buildcfg
    13  
    14  import (
    15  	"fmt"
    16  	"os"
    17  	"path/filepath"
    18  	"runtime"
    19  	"strings"
    20  )
    21  
    22  var (
    23  	GOROOT   = runtime.GOROOT() // cached for efficiency
    24  	GOARCH   = envOr("GOARCH", defaultGOARCH)
    25  	GOOS     = envOr("GOOS", defaultGOOS)
    26  	GO386    = envOr("GO386", defaultGO386)
    27  	GOAMD64  = goamd64()
    28  	GOARM    = goarm()
    29  	GOMIPS   = gomips()
    30  	GOMIPS64 = gomips64()
    31  	GOPPC64  = goppc64()
    32  	GOWASM   = gowasm()
    33  	ToolTags = toolTags()
    34  	GO_LDSO  = defaultGO_LDSO
    35  	Version  = version
    36  )
    37  
    38  // Error is one of the errors found (if any) in the build configuration.
    39  var Error error
    40  
    41  // Check exits the program with a fatal error if Error is non-nil.
    42  func Check() {
    43  	if Error != nil {
    44  		fmt.Fprintf(os.Stderr, "%s: %v\n", filepath.Base(os.Args[0]), Error)
    45  		os.Exit(2)
    46  	}
    47  }
    48  
    49  func envOr(key, value string) string {
    50  	if x := os.Getenv(key); x != "" {
    51  		return x
    52  	}
    53  	return value
    54  }
    55  
    56  func goamd64() int {
    57  	switch v := envOr("GOAMD64", defaultGOAMD64); v {
    58  	case "v1":
    59  		return 1
    60  	case "v2":
    61  		return 2
    62  	case "v3":
    63  		return 3
    64  	case "v4":
    65  		return 4
    66  	}
    67  	Error = fmt.Errorf("invalid GOAMD64: must be v1, v2, v3, v4")
    68  	return int(defaultGOAMD64[len("v")] - '0')
    69  }
    70  
    71  func goarm() int {
    72  	def := defaultGOARM
    73  	if GOOS == "android" && GOARCH == "arm" {
    74  		// Android arm devices always support GOARM=7.
    75  		def = "7"
    76  	}
    77  	switch v := envOr("GOARM", def); v {
    78  	case "5":
    79  		return 5
    80  	case "6":
    81  		return 6
    82  	case "7":
    83  		return 7
    84  	}
    85  	Error = fmt.Errorf("invalid GOARM: must be 5, 6, 7")
    86  	return int(def[0] - '0')
    87  }
    88  
    89  func gomips() string {
    90  	switch v := envOr("GOMIPS", defaultGOMIPS); v {
    91  	case "hardfloat", "softfloat":
    92  		return v
    93  	}
    94  	Error = fmt.Errorf("invalid GOMIPS: must be hardfloat, softfloat")
    95  	return defaultGOMIPS
    96  }
    97  
    98  func gomips64() string {
    99  	switch v := envOr("GOMIPS64", defaultGOMIPS64); v {
   100  	case "hardfloat", "softfloat":
   101  		return v
   102  	}
   103  	Error = fmt.Errorf("invalid GOMIPS64: must be hardfloat, softfloat")
   104  	return defaultGOMIPS64
   105  }
   106  
   107  func goppc64() int {
   108  	switch v := envOr("GOPPC64", defaultGOPPC64); v {
   109  	case "power8":
   110  		return 8
   111  	case "power9":
   112  		return 9
   113  	case "power10":
   114  		return 10
   115  	}
   116  	Error = fmt.Errorf("invalid GOPPC64: must be power8, power9, power10")
   117  	return int(defaultGOPPC64[len("power")] - '0')
   118  }
   119  
   120  type gowasmFeatures struct {
   121  	SatConv bool
   122  	SignExt bool
   123  }
   124  
   125  func (f gowasmFeatures) String() string {
   126  	var flags []string
   127  	if f.SatConv {
   128  		flags = append(flags, "satconv")
   129  	}
   130  	if f.SignExt {
   131  		flags = append(flags, "signext")
   132  	}
   133  	return strings.Join(flags, ",")
   134  }
   135  
   136  func gowasm() (f gowasmFeatures) {
   137  	for _, opt := range strings.Split(envOr("GOWASM", ""), ",") {
   138  		switch opt {
   139  		case "satconv":
   140  			f.SatConv = true
   141  		case "signext":
   142  			f.SignExt = true
   143  		case "":
   144  			// ignore
   145  		default:
   146  			Error = fmt.Errorf("invalid GOWASM: no such feature %q", opt)
   147  		}
   148  	}
   149  	return
   150  }
   151  
   152  func Getgoextlinkenabled() string {
   153  	return envOr("GO_EXTLINK_ENABLED", defaultGO_EXTLINK_ENABLED)
   154  }
   155  
   156  func toolTags() []string {
   157  	tags := experimentTags()
   158  	tags = append(tags, gogoarchTags()...)
   159  	return tags
   160  }
   161  
   162  func experimentTags() []string {
   163  	var list []string
   164  	// For each experiment that has been enabled in the toolchain, define a
   165  	// build tag with the same name but prefixed by "goexperiment." which can be
   166  	// used for compiling alternative files for the experiment. This allows
   167  	// changes for the experiment, like extra struct fields in the runtime,
   168  	// without affecting the base non-experiment code at all.
   169  	for _, exp := range Experiment.Enabled() {
   170  		list = append(list, "goexperiment."+exp)
   171  	}
   172  	return list
   173  }
   174  
   175  // GOGOARCH returns the name and value of the GO$GOARCH setting.
   176  // For example, if GOARCH is "amd64" it might return "GOAMD64", "v2".
   177  func GOGOARCH() (name, value string) {
   178  	switch GOARCH {
   179  	case "386":
   180  		return "GO386", GO386
   181  	case "amd64":
   182  		return "GOAMD64", fmt.Sprintf("v%d", GOAMD64)
   183  	case "arm":
   184  		return "GOARM", fmt.Sprintf("%d", GOARM)
   185  	case "mips", "mipsle":
   186  		return "GOMIPS", GOMIPS
   187  	case "mips64", "mips64le":
   188  		return "GOMIPS64", GOMIPS64
   189  	case "ppc64", "ppc64le":
   190  		return "GOPPC64", fmt.Sprintf("power%d", GOPPC64)
   191  	case "wasm":
   192  		return "GOWASM", GOWASM.String()
   193  	}
   194  	return "", ""
   195  }
   196  
   197  func gogoarchTags() []string {
   198  	switch GOARCH {
   199  	case "386":
   200  		return []string{GOARCH + "." + GO386}
   201  	case "amd64":
   202  		var list []string
   203  		for i := 1; i <= GOAMD64; i++ {
   204  			list = append(list, fmt.Sprintf("%s.v%d", GOARCH, i))
   205  		}
   206  		return list
   207  	case "arm":
   208  		var list []string
   209  		for i := 5; i <= GOARM; i++ {
   210  			list = append(list, fmt.Sprintf("%s.%d", GOARCH, i))
   211  		}
   212  		return list
   213  	case "mips", "mipsle":
   214  		return []string{GOARCH + "." + GOMIPS}
   215  	case "mips64", "mips64le":
   216  		return []string{GOARCH + "." + GOMIPS64}
   217  	case "ppc64", "ppc64le":
   218  		var list []string
   219  		for i := 8; i <= GOPPC64; i++ {
   220  			list = append(list, fmt.Sprintf("%s.power%d", GOARCH, i))
   221  		}
   222  		return list
   223  	case "wasm":
   224  		var list []string
   225  		if GOWASM.SatConv {
   226  			list = append(list, GOARCH+".satconv")
   227  		}
   228  		if GOWASM.SignExt {
   229  			list = append(list, GOARCH+".signext")
   230  		}
   231  		return list
   232  	}
   233  	return nil
   234  }