github.com/sirkon/goproxy@v1.4.8/internal/envcmd/env.go (about)

     1  // Copyright 2012 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 envcmd implements the ``go env'' command.
     6  package envcmd
     7  
     8  import (
     9  	"encoding/json"
    10  	"fmt"
    11  	"os"
    12  	"path/filepath"
    13  	"runtime"
    14  	"strings"
    15  
    16  	"github.com/sirkon/goproxy/internal/base"
    17  	"github.com/sirkon/goproxy/internal/cache"
    18  	"github.com/sirkon/goproxy/internal/cfg"
    19  	"github.com/sirkon/goproxy/internal/load"
    20  	"github.com/sirkon/goproxy/internal/modload"
    21  	"github.com/sirkon/goproxy/internal/work"
    22  )
    23  
    24  var CmdEnv = &base.Command{
    25  	UsageLine: "go env [-json] [var ...]",
    26  	Short:     "print Go environment information",
    27  	Long: `
    28  Env prints Go environment information.
    29  
    30  By default env prints information as a shell cache
    31  (on Windows, a batch file). If one or more variable
    32  names is given as arguments, env prints the value of
    33  each named variable on its own line.
    34  
    35  The -json flag prints the environment in JSON format
    36  instead of as a shell cache.
    37  
    38  For more about environment variables, see 'go help environment'.
    39  	`,
    40  }
    41  
    42  func init() {
    43  	CmdEnv.Run = runEnv // break init cycle
    44  }
    45  
    46  var envJson = CmdEnv.Flag.Bool("json", false, "")
    47  
    48  func MkEnv() []cfg.EnvVar {
    49  	var b work.Builder
    50  	b.Init()
    51  
    52  	env := []cfg.EnvVar{
    53  		{Name: "GOARCH", Value: cfg.Goarch},
    54  		{Name: "GOBIN", Value: cfg.GOBIN},
    55  		{Name: "GOCACHE", Value: cache.DefaultDir()},
    56  		{Name: "GOEXE", Value: cfg.ExeSuffix},
    57  		{Name: "GOFLAGS", Value: os.Getenv("GOFLAGS")},
    58  		{Name: "GOHOSTARCH", Value: runtime.GOARCH},
    59  		{Name: "GOHOSTOS", Value: runtime.GOOS},
    60  		{Name: "GOOS", Value: cfg.Goos},
    61  		{Name: "GOPATH", Value: cfg.BuildContext.GOPATH},
    62  		{Name: "GOPROXY", Value: os.Getenv("GOPROXY")},
    63  		{Name: "GORACE", Value: os.Getenv("GORACE")},
    64  		{Name: "GOROOT", Value: cfg.GOROOT},
    65  		{Name: "GOTMPDIR", Value: os.Getenv("GOTMPDIR")},
    66  		{Name: "GOTOOLDIR", Value: base.ToolDir},
    67  	}
    68  
    69  	if work.GccgoBin != "" {
    70  		env = append(env, cfg.EnvVar{Name: "GCCGO", Value: work.GccgoBin})
    71  	} else {
    72  		env = append(env, cfg.EnvVar{Name: "GCCGO", Value: work.GccgoName})
    73  	}
    74  
    75  	switch cfg.Goarch {
    76  	case "arm":
    77  		env = append(env, cfg.EnvVar{Name: "GOARM", Value: cfg.GOARM})
    78  	case "386":
    79  		env = append(env, cfg.EnvVar{Name: "GO386", Value: cfg.GO386})
    80  	case "mips", "mipsle":
    81  		env = append(env, cfg.EnvVar{Name: "GOMIPS", Value: cfg.GOMIPS})
    82  	case "mips64", "mips64le":
    83  		env = append(env, cfg.EnvVar{Name: "GOMIPS64", Value: cfg.GOMIPS64})
    84  	}
    85  
    86  	cc := cfg.DefaultCC(cfg.Goos, cfg.Goarch)
    87  	if env := strings.Fields(os.Getenv("CC")); len(env) > 0 {
    88  		cc = env[0]
    89  	}
    90  	cxx := cfg.DefaultCXX(cfg.Goos, cfg.Goarch)
    91  	if env := strings.Fields(os.Getenv("CXX")); len(env) > 0 {
    92  		cxx = env[0]
    93  	}
    94  	env = append(env, cfg.EnvVar{Name: "CC", Value: cc})
    95  	env = append(env, cfg.EnvVar{Name: "CXX", Value: cxx})
    96  
    97  	if cfg.BuildContext.CgoEnabled {
    98  		env = append(env, cfg.EnvVar{Name: "CGO_ENABLED", Value: "1"})
    99  	} else {
   100  		env = append(env, cfg.EnvVar{Name: "CGO_ENABLED", Value: "0"})
   101  	}
   102  
   103  	return env
   104  }
   105  
   106  func findEnv(env []cfg.EnvVar, name string) string {
   107  	for _, e := range env {
   108  		if e.Name == name {
   109  			return e.Value
   110  		}
   111  	}
   112  	return ""
   113  }
   114  
   115  // ExtraEnvVars returns environment variables that should not leak into child processes.
   116  func ExtraEnvVars() []cfg.EnvVar {
   117  	gomod := ""
   118  	if modload.Init(); modload.ModRoot != "" {
   119  		gomod = filepath.Join(modload.ModRoot, "go.mod")
   120  	}
   121  	return []cfg.EnvVar{
   122  		{Name: "GOMOD", Value: gomod},
   123  	}
   124  }
   125  
   126  // ExtraEnvVarsCostly returns environment variables that should not leak into child processes
   127  // but are costly to evaluate.
   128  func ExtraEnvVarsCostly() []cfg.EnvVar {
   129  	var b work.Builder
   130  	b.Init()
   131  	cppflags, cflags, cxxflags, fflags, ldflags, err := b.CFlags(&load.Package{})
   132  	if err != nil {
   133  		// Should not happen - b.CFlags was given an empty package.
   134  		fmt.Fprintf(os.Stderr, "go: invalid cflags: %v\n", err)
   135  		return nil
   136  	}
   137  	cmd := b.GccCmd(".", "")
   138  
   139  	return []cfg.EnvVar{
   140  		// Note: Update the switch in runEnv below when adding to this list.
   141  		{Name: "CGO_CFLAGS", Value: strings.Join(cflags, " ")},
   142  		{Name: "CGO_CPPFLAGS", Value: strings.Join(cppflags, " ")},
   143  		{Name: "CGO_CXXFLAGS", Value: strings.Join(cxxflags, " ")},
   144  		{Name: "CGO_FFLAGS", Value: strings.Join(fflags, " ")},
   145  		{Name: "CGO_LDFLAGS", Value: strings.Join(ldflags, " ")},
   146  		{Name: "PKG_CONFIG", Value: b.PkgconfigCmd()},
   147  		{Name: "GOGCCFLAGS", Value: strings.Join(cmd[3:], " ")},
   148  	}
   149  }
   150  
   151  func runEnv(cmd *base.Command, args []string) {
   152  	env := cfg.CmdEnv
   153  	env = append(env, ExtraEnvVars()...)
   154  
   155  	// Do we need to call ExtraEnvVarsCostly, which is a bit expensive?
   156  	// Only if we're listing all environment variables ("go env")
   157  	// or the variables being requested are in the extra list.
   158  	needCostly := true
   159  	if len(args) > 0 {
   160  		needCostly = false
   161  		for _, arg := range args {
   162  			switch arg {
   163  			case "CGO_CFLAGS",
   164  				"CGO_CPPFLAGS",
   165  				"CGO_CXXFLAGS",
   166  				"CGO_FFLAGS",
   167  				"CGO_LDFLAGS",
   168  				"PKG_CONFIG",
   169  				"GOGCCFLAGS":
   170  				needCostly = true
   171  			}
   172  		}
   173  	}
   174  	if needCostly {
   175  		env = append(env, ExtraEnvVarsCostly()...)
   176  	}
   177  
   178  	if len(args) > 0 {
   179  		if *envJson {
   180  			var es []cfg.EnvVar
   181  			for _, name := range args {
   182  				e := cfg.EnvVar{Name: name, Value: findEnv(env, name)}
   183  				es = append(es, e)
   184  			}
   185  			printEnvAsJSON(es)
   186  		} else {
   187  			for _, name := range args {
   188  				fmt.Printf("%s\n", findEnv(env, name))
   189  			}
   190  		}
   191  		return
   192  	}
   193  
   194  	if *envJson {
   195  		printEnvAsJSON(env)
   196  		return
   197  	}
   198  
   199  	for _, e := range env {
   200  		if e.Name != "TERM" {
   201  			switch runtime.GOOS {
   202  			default:
   203  				fmt.Printf("%s=\"%s\"\n", e.Name, e.Value)
   204  			case "plan9":
   205  				if strings.IndexByte(e.Value, '\x00') < 0 {
   206  					fmt.Printf("%s='%s'\n", e.Name, strings.Replace(e.Value, "'", "''", -1))
   207  				} else {
   208  					v := strings.Split(e.Value, "\x00")
   209  					fmt.Printf("%s=(", e.Name)
   210  					for x, s := range v {
   211  						if x > 0 {
   212  							fmt.Printf(" ")
   213  						}
   214  						fmt.Printf("%s", s)
   215  					}
   216  					fmt.Printf(")\n")
   217  				}
   218  			case "windows":
   219  				fmt.Printf("set %s=%s\n", e.Name, e.Value)
   220  			}
   221  		}
   222  	}
   223  }
   224  
   225  func printEnvAsJSON(env []cfg.EnvVar) {
   226  	m := make(map[string]string)
   227  	for _, e := range env {
   228  		if e.Name == "TERM" {
   229  			continue
   230  		}
   231  		m[e.Name] = e.Value
   232  	}
   233  	enc := json.NewEncoder(os.Stdout)
   234  	enc.SetIndent("", "\t")
   235  	if err := enc.Encode(m); err != nil {
   236  		base.Fatalf("%s", err)
   237  	}
   238  }