github.com/MangoDowner/go-gm@v0.0.0-20180818020936-8baa2bd4408c/src/cmd/go/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  	"runtime"
    13  	"strings"
    14  
    15  	"cmd/go/internal/base"
    16  	"cmd/go/internal/cfg"
    17  	"cmd/go/internal/load"
    18  	"cmd/go/internal/work"
    19  )
    20  
    21  var CmdEnv = &base.Command{
    22  	UsageLine: "env [-json] [var ...]",
    23  	Short:     "print Go environment information",
    24  	Long: `
    25  Env prints Go environment information.
    26  
    27  By default env prints information as a shell script
    28  (on Windows, a batch file). If one or more variable
    29  names is given as arguments, env prints the value of
    30  each named variable on its own line.
    31  
    32  The -json flag prints the environment in JSON format
    33  instead of as a shell script.
    34  	`,
    35  }
    36  
    37  func init() {
    38  	CmdEnv.Run = runEnv // break init cycle
    39  }
    40  
    41  var envJson = CmdEnv.Flag.Bool("json", false, "")
    42  
    43  func MkEnv() []cfg.EnvVar {
    44  	var b work.Builder
    45  	b.Init()
    46  
    47  	env := []cfg.EnvVar{
    48  		{Name: "GOARCH", Value: cfg.Goarch},
    49  		{Name: "GOBIN", Value: cfg.GOBIN},
    50  		{Name: "GOEXE", Value: cfg.ExeSuffix},
    51  		{Name: "GOHOSTARCH", Value: runtime.GOARCH},
    52  		{Name: "GOHOSTOS", Value: runtime.GOOS},
    53  		{Name: "GOOS", Value: cfg.Goos},
    54  		{Name: "GOPATH", Value: cfg.BuildContext.GOPATH},
    55  		{Name: "GORACE", Value: os.Getenv("GORACE")},
    56  		{Name: "GOROOT", Value: cfg.GOROOT},
    57  		{Name: "GOTOOLDIR", Value: base.ToolDir},
    58  
    59  		// disable escape codes in clang errors
    60  		{Name: "TERM", Value: "dumb"},
    61  	}
    62  
    63  	if work.GccgoBin != "" {
    64  		env = append(env, cfg.EnvVar{Name: "GCCGO", Value: work.GccgoBin})
    65  	} else {
    66  		env = append(env, cfg.EnvVar{Name: "GCCGO", Value: work.GccgoName})
    67  	}
    68  
    69  	switch cfg.Goarch {
    70  	case "arm":
    71  		env = append(env, cfg.EnvVar{Name: "GOARM", Value: cfg.GOARM})
    72  	case "386":
    73  		env = append(env, cfg.EnvVar{Name: "GO386", Value: cfg.GO386})
    74  	}
    75  
    76  	cmd := b.GccCmd(".")
    77  	env = append(env, cfg.EnvVar{Name: "CC", Value: cmd[0]})
    78  	env = append(env, cfg.EnvVar{Name: "GOGCCFLAGS", Value: strings.Join(cmd[3:], " ")})
    79  	cmd = b.GxxCmd(".")
    80  	env = append(env, cfg.EnvVar{Name: "CXX", Value: cmd[0]})
    81  
    82  	if cfg.BuildContext.CgoEnabled {
    83  		env = append(env, cfg.EnvVar{Name: "CGO_ENABLED", Value: "1"})
    84  	} else {
    85  		env = append(env, cfg.EnvVar{Name: "CGO_ENABLED", Value: "0"})
    86  	}
    87  
    88  	return env
    89  }
    90  
    91  func findEnv(env []cfg.EnvVar, name string) string {
    92  	for _, e := range env {
    93  		if e.Name == name {
    94  			return e.Value
    95  		}
    96  	}
    97  	return ""
    98  }
    99  
   100  // ExtraEnvVars returns environment variables that should not leak into child processes.
   101  func ExtraEnvVars() []cfg.EnvVar {
   102  	var b work.Builder
   103  	b.Init()
   104  	cppflags, cflags, cxxflags, fflags, ldflags, err := b.CFlags(&load.Package{})
   105  	if err != nil {
   106  		// Should not happen - b.CFlags was given an empty package.
   107  		fmt.Fprintf(os.Stderr, "go: invalid cflags: %v\n", err)
   108  		return nil
   109  	}
   110  	return []cfg.EnvVar{
   111  		{Name: "CGO_CFLAGS", Value: strings.Join(cflags, " ")},
   112  		{Name: "CGO_CPPFLAGS", Value: strings.Join(cppflags, " ")},
   113  		{Name: "CGO_CXXFLAGS", Value: strings.Join(cxxflags, " ")},
   114  		{Name: "CGO_FFLAGS", Value: strings.Join(fflags, " ")},
   115  		{Name: "CGO_LDFLAGS", Value: strings.Join(ldflags, " ")},
   116  		{Name: "PKG_CONFIG", Value: b.PkgconfigCmd()},
   117  	}
   118  }
   119  
   120  func runEnv(cmd *base.Command, args []string) {
   121  	env := cfg.CmdEnv
   122  	env = append(env, ExtraEnvVars()...)
   123  	if len(args) > 0 {
   124  		if *envJson {
   125  			var es []cfg.EnvVar
   126  			for _, name := range args {
   127  				e := cfg.EnvVar{Name: name, Value: findEnv(env, name)}
   128  				es = append(es, e)
   129  			}
   130  			printEnvAsJSON(es)
   131  		} else {
   132  			for _, name := range args {
   133  				fmt.Printf("%s\n", findEnv(env, name))
   134  			}
   135  		}
   136  		return
   137  	}
   138  
   139  	if *envJson {
   140  		printEnvAsJSON(env)
   141  		return
   142  	}
   143  
   144  	for _, e := range env {
   145  		if e.Name != "TERM" {
   146  			switch runtime.GOOS {
   147  			default:
   148  				fmt.Printf("%s=\"%s\"\n", e.Name, e.Value)
   149  			case "plan9":
   150  				if strings.IndexByte(e.Value, '\x00') < 0 {
   151  					fmt.Printf("%s='%s'\n", e.Name, strings.Replace(e.Value, "'", "''", -1))
   152  				} else {
   153  					v := strings.Split(e.Value, "\x00")
   154  					fmt.Printf("%s=(", e.Name)
   155  					for x, s := range v {
   156  						if x > 0 {
   157  							fmt.Printf(" ")
   158  						}
   159  						fmt.Printf("%s", s)
   160  					}
   161  					fmt.Printf(")\n")
   162  				}
   163  			case "windows":
   164  				fmt.Printf("set %s=%s\n", e.Name, e.Value)
   165  			}
   166  		}
   167  	}
   168  }
   169  
   170  func printEnvAsJSON(env []cfg.EnvVar) {
   171  	m := make(map[string]string)
   172  	for _, e := range env {
   173  		if e.Name == "TERM" {
   174  			continue
   175  		}
   176  		m[e.Name] = e.Value
   177  	}
   178  	enc := json.NewEncoder(os.Stdout)
   179  	enc.SetIndent("", "\t")
   180  	if err := enc.Encode(m); err != nil {
   181  		base.Fatalf("%s", err)
   182  	}
   183  }